From da95af1971b8ea0069b12182f026a51e92d87be9 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 19 Sep 2023 20:40:36 +0000 Subject: [PATCH 001/106] sm r3.4 --- tools/imagesets/oracle8conda/distrib_nisar/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/imagesets/oracle8conda/distrib_nisar/Dockerfile b/tools/imagesets/oracle8conda/distrib_nisar/Dockerfile index c34cb42af..45ecd19c0 100644 --- a/tools/imagesets/oracle8conda/distrib_nisar/Dockerfile +++ b/tools/imagesets/oracle8conda/distrib_nisar/Dockerfile @@ -12,7 +12,7 @@ RUN cd /opt \ && git clone https://$GIT_OAUTH_TOKEN@github-fn.jpl.nasa.gov/NISAR-ADT/SoilMoisture \ && git clone https://$GIT_OAUTH_TOKEN@github-fn.jpl.nasa.gov/NISAR-ADT/QualityAssurance \ && cd /opt/QualityAssurance && git checkout v4.0.0 && rm -rf .git \ - && cd /opt/SoilMoisture && git checkout f62fe7b47001aea2195f3c8e88d5f7d3a30e71a7 && rm -rf .git + && cd /opt/SoilMoisture && git checkout 93a364c05de2819fce0df704126320cfb5face68 && rm -rf .git FROM $distrib_img From 16c8feddbad2e90bb4f71f6aee4396ed3d902649 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 9 Oct 2023 21:08:13 +0000 Subject: [PATCH 002/106] copy LY common band filter source codes --- .vscode/settings.json | 5 + cxx/isce3/signal/Crossmul.cpp | 166 +++++++++++++++++++++++++++++++++- cxx/isce3/signal/Crossmul.h | 84 ++++++++++++++++- cxx/isce3/signal/Crossmul.icc | 1 + cxx/isce3/signal/Filter.cpp | 30 +++--- 5 files changed, 269 insertions(+), 17 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..801f50371 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "*.icc": "cpp" + } +} \ No newline at end of file diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 44d19b4fa..a714fd570 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -59,18 +59,104 @@ void lookdownShiftImpact(size_t oversample, size_t fft_size, size_t blockRows, // Utility function to get number of OpenMP threads // (gcc sometimes has problems with omp_get_num_threads) size_t omp_thread_count() { + // may use the omp_get_num_procs() size_t n = 0; #pragma omp parallel reduction(+:n) n += 1; return n; } +/** +* @param[in] refSlc a block of the reference SLC to be filtered +* @param[in] secSlc a block of second SLC to be filtered +* @param[in] geometryIfgram a simulated interferogram that contains the geometrical phase due to baseline separation +* @param[in] geometryIfgramConj conjugate of geometryIfgram +* @param[in] refSpectrum spectrum of geometryIfgramConj in range direction +* @param[in] secSpectrum spectrum of geometryIfgram in range direction +* @param[in] rangeFrequencies frequencies in range direction +* @param[in] rngFilter a filter object +* @param[in] blockLength number of rows +* @param[in] ncols number of columns +*/ +void isce3::signal::Crossmul:: +rangeCommonBandFilter(std::valarray> &refSlc, + std::valarray> &secSlc, + std::valarray> geometryIfgram, + std::valarray> geometryIfgramConj, + std::valarray> &refSpectrum, + std::valarray> &secSpectrum, + std::valarray &rangeFrequencies, + isce3::signal::Filter &rngFilter, + size_t blockLength, + size_t ncols) +{ + // size of the arrays + size_t vectorLength = refSlc.size(); + + // Aligning the spectrum of the two SLCs + // Shifting the range spectrum of each image according to the local + // (slope-dependent) wavenumber. This shift in frequency domain is + // achieved by removing/adding the geometrical (representing topography) + // from/to reference and secondary SLCs in time domain. + refSlc *= geometryIfgramConj; + secSlc *= geometryIfgram; + + // range frequency shift + double frequencyShift = 0.0; + + // determine the frequency shift based on the power spectral density of + // the geometrical interferometric phase using an empirical approach + rangeFrequencyShift(refSpectrum, + secSpectrum, + rangeFrequencies, + blockLength, + ncols, + frequencyShift); + + std::cout << "frequencyShift : "<< frequencyShift << std::endl; + std::cout << "range bandwidth: " << _rangeBandwidth << std::endl; + + // Since the spectrum of the ref and sec SLCs are already aligned, + // we design the low-pass filter as a band-pass at zero frequency with + // bandwidth of (W - frequency shift) + std::valarray filterCenterFrequency{0.0}; + std::valarray filterBandwidth{_rangeBandwidth - fabs(frequencyShift)}; + std::string filterType = "cosine"; + + // Contruct the low pass filter for this block. This filter is + // common for both SLCs + rngFilter.constructRangeBandpassFilter(_rangeSamplingFrequency, + filterCenterFrequency, + filterBandwidth, + ncols, + blockLength, + filterType); + + // low pass filter the ref and sec slc + rngFilter.filter(refSlc, refSpectrum); + rngFilter.filter(secSlc, secSpectrum); + + // add/remove half geometrical phase to/from reference and secondary SLCs + #pragma omp parallel for + for (size_t i = 0; i < vectorLength; ++i) { + + // Half phase due to baseline separation obtained from range difference + // from reference and secondary antennas to the target (i.e., range + // offset derived from geometrical coregistration) + double halfPhase = std::arg(geometryIfgram[i]) / 2.0; + refSlc[i] *= + std::complex(std::cos(halfPhase), std::sin(halfPhase)); + secSlc[i] *= std::complex(std::cos(halfPhase), + -1 * std::sin(halfPhase)); + } +} + void isce3::signal::Crossmul:: crossmul(isce3::io::Raster& refSlcRaster, isce3::io::Raster& secSlcRaster, isce3::io::Raster& ifgRaster, isce3::io::Raster& coherenceRaster, - isce3::io::Raster* rngOffsetRaster) const + isce3::io::Raster* rngOffsetRaster) { // setting local lines per block to avoid modifying class member size_t linesPerBlock = _linesPerBlock; @@ -173,6 +259,9 @@ crossmul(isce3::io::Raster& refSlcRaster, // storage for a simulated interferogram which its phase is the // interferometric phase due to the imaging geometry: // phase = (4*PI/wavelength)*(rangePixelSpacing)*(rngOffset) + + std::valarray> geometryIfgram; + // complex conjugate of geometryIfgram std::valarray> geometryIfgramConj(spectrumSize); @@ -252,6 +341,34 @@ crossmul(isce3::io::Raster& refSlcRaster, lookdownShiftImpact(_oversampleFactor, fft_size, linesPerBlock, shiftImpact); + //filter objects which will be used for azimuth and range common band filtering + isce3::signal::Filter azimuthFilter; + isce3::signal::Filter rangeFilter; + + // Declare valarray for range frequencies used by filter + std::valarray rangeFrequencies; + + // Declare valarray for azimuth spectrum used by filter + std::valarray> refAzimuthSpectrum; + + if (_doCommonAzimuthBandFilter) { + // Allocate storage for azimuth spectrum + refAzimuthSpectrum.resize(spectrumSize); + + // Construct azimuth common band filter for a block of data + azimuthFilter.constructAzimuthCommonbandFilter( + _refDoppler, _secDoppler, _commonAzimuthBandwidth, + _prf, _beta, refSlc, refAzimuthSpectrum, fft_size, + linesPerBlock); + } + + if (_doCommonRangeBandFilter) { + geometryIfgram.resize(spectrumSize); + rangeFrequencies.resize(fft_size); + // TODO determine what this does and document + fftfreq(1.0/_rangeSamplingFrequency, rangeFrequencies); + } + // loop over all blocks std::cout << "nblocks : " << nblocks << std::endl; @@ -286,6 +403,53 @@ crossmul(isce3::io::Raster& refSlcRaster, secSlc[std::slice(line*fft_size, ncols, 1)] = dataLine; } + //common azimuth band-pass filter the reference and secondary SLCs + if (_doCommonAzimuthBandFilter) { + azimuthFilter.filter(refSlc, refAzimuthSpectrum); + azimuthFilter.filter(secSlc, refAzimuthSpectrum); + } + + // common range band-pass filtering + if (_doCommonRangeBandFilter) { + + // Some diagnostic messages to make sure everything has been configured + // TODO use journal instead of cout + std::cout << " - range pixel spacing: " << _rangePixelSpacing << std::endl; + std::cout << " - wavelength: " << _wavelength << std::endl; + + // Read range offsets + std::valarray offsetLine(ncols); + for (size_t line = 0; line < blockRowsData; ++line) { + rngOffsetRaster->getLine(offsetLine, rowStart + line); + rngOffset[std::slice(line*ncols, ncols, 1)] = offsetLine; + } + + // Convert range offset from meters to complex phase + #pragma omp parallel for + for (size_t line = 0; line < blockRowsData; ++line) { + for (size_t col = 0; col < ncols; ++col) { + double phase = 4.0 * M_PI + * _rangePixelSpacing*rngOffset[line*ncols+col] + / _wavelength; + + geometryIfgram[line*fft_size + col] = + std::complex (std::cos(phase), std::sin(phase)); + geometryIfgramConj[line*fft_size + col] = + std::complex (std::cos(phase), -1.0*std::sin(phase)); + } + } + + // Forward FFT to compute topo-dependent spectrum + refSignal.forward(geometryIfgramConj, refSpectrum); + refSignal.forward(geometryIfgram, secSpectrum); + + // Apply range common band filter to ref and sec SLC + rangeCommonBandFilter(refSlc, secSlc, geometryIfgram, + geometryIfgramConj, refSpectrum, secSpectrum, + rangeFrequencies, rangeFilter, blockRowsData, fft_size); + + } + // upsample the reference and secondary SLCs if (_oversampleFactor == 1) { refSlcUpsampled = refSlc; diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 54b75e677..9edea5e70 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -31,7 +31,7 @@ class isce3::signal::Crossmul { isce3::io::Raster& secSlcRaster, isce3::io::Raster& ifgRaster, isce3::io::Raster& coherence, - isce3::io::Raster* rngOffsetRaster = nullptr) const; + isce3::io::Raster* rngOffsetRaster = nullptr); /** Set doppler LUTs for reference and secondary SLCs*/ inline void doppler(isce3::core::LUT1d, @@ -73,6 +73,54 @@ class isce3::signal::Crossmul { /** Get number of azimuth looks */ inline int azimuthLooks() const { return _azimuthLooks; } + /** Set common azimuth band filtering flag */ + inline void doCommonAzimuthBandFilter(bool doAzBandFilter) { + _doCommonAzimuthBandFilter = doAzBandFilter; } + + /** Get common azimuth band filtering flag */ + inline bool doCommonAzimuthBandFilter() const { + return _doCommonAzimuthBandFilter; } + + /** Set azimuth common bandwidth */ + inline void commonAzimuthBandwidth(double azBandwidth) { + _commonAzimuthBandwidth = azBandwidth; } + + /** Get azimuth common bandwidth */ + inline double commonAzimuthBandwidth() const { + return _commonAzimuthBandwidth; } + + /** Set beta parameter for the azimuth common band filter */ + inline void beta(double beta) { _beta = beta; } + + /** Get beta parameter for the azimuth common band filter */ + inline double beta() const { return _beta; } + + /** Set common range band filtering flag */ + inline void doCommonRangeBandFilter(bool doRgBandFilter) { + _doCommonRangeBandFilter = doRgBandFilter; } + + /** Get common range band filtering flag */ + inline bool doCommonRangeBandFilter() const { + return _doCommonRangeBandFilter; } + + /** Set pulse repetition frequency (PRF) */ + inline void prf(double prf) { _prf = prf; } + + /** Get pulse repetition frequency (PRF) */ + inline double prf() const { return _prf; } + + /** Set range sampling frequency */ + inline void rangeSamplingFrequency(double rgSamplingFreq) { _rangeSamplingFrequency = rgSamplingFreq; } + + /** Get range sampling frequency */ + inline double rangeSamplingFrequency() const { return _rangeSamplingFrequency; } + + /** Set the range bandwidth */ + inline void rangeBandwidth(double rngBandwidth) { _rangeBandwidth = rngBandwidth; } + + /** Get the range bandwidth */ + inline double rangeBandwidth() const {return _rangeBandwidth; } + /** Set oversample factor */ inline void oversampleFactor(size_t oversamp) { _oversampleFactor = oversamp; } @@ -100,6 +148,18 @@ class isce3::signal::Crossmul { inline void getPeakIndex(std::valarray data, size_t &peakIndex); + /** Range common band filtering*/ + void rangeCommonBandFilter(std::valarray> &refSlc, + std::valarray> &secSlc, + std::valarray> geometryIfgram, + std::valarray> geometryIfgramConj, + std::valarray> &refSpectrum, + std::valarray> &secSpectrum, + std::valarray &rangeFrequencies, + isce3::signal::Filter &rngFilter, + size_t blockRows, + size_t ncols); + private: //Doppler LUT for the refernce SLC isce3::core::LUT1d _refDoppler; @@ -121,6 +181,28 @@ class isce3::signal::Crossmul { bool _multiLookEnabled = false; + // Flag for common azimuth band filtering + bool _doCommonAzimuthBandFilter = false; + + // Azimuth common bandwidth + // TODO make a part of constructor? + double _commonAzimuthBandwidth; + + // Beta parameter for constructing common azimuth band filter + double _beta; + + // Flag for common range band filtering + bool _doCommonRangeBandFilter = false; + + //pulse repetition frequency + double _prf; + + // range samping frequency + double _rangeSamplingFrequency; + + // range signal bandwidth + double _rangeBandwidth; + // number of lines per block size_t _linesPerBlock = 1024; diff --git a/cxx/isce3/signal/Crossmul.icc b/cxx/isce3/signal/Crossmul.icc index 742d63e2c..9f30e50dc 100644 --- a/cxx/isce3/signal/Crossmul.icc +++ b/cxx/isce3/signal/Crossmul.icc @@ -85,6 +85,7 @@ rangeFrequencyShift(std::valarray> &refSpectrum, std::valarray secAvgSpectrum(fft_size); secAvgSpectrum = 0.0; + #pragma omp parallel for for (size_t line = 0; line < linesPerBlock; ++line){ for (size_t col = 0; col < fft_size; ++col){ refAvgSpectrum[col] += std::abs(refSpectrum[line*fft_size + col]); diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index c414f7c69..2dcc8fd7b 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -24,7 +24,7 @@ initiateRangeFilter(std::valarray> &signal, size_t nrows) { _signal.forwardRangeFFT(signal, spectrum, ncols, nrows); - _signal.inverseRangeFFT(spectrum, signal, ncols, nrows); + _signal.inverseRangeFFT(spectrum, signal, ncols, nrows); } /** @@ -77,7 +77,7 @@ constructRangeBandpassFilter(double rangeSamplingFrequency, _signal.forwardRangeFFT(signal, spectrum, ncols, nrows); _signal.inverseRangeFFT(spectrum, signal, ncols, nrows); - + } template @@ -138,7 +138,7 @@ constructRangeBandpassFilter(double rangeSamplingFrequency, * @param[in] subBandBandwidths a vector of bandwidths for each band * @param[in] dt samplig rate of the signal * @param[in] fft_size length of the spectrum - * @param[out] _filter1D one dimensional boxcar bandpass filter in frequency domain + * @param[out] _filter1D one dimensional boxcar bandpass filter in frequency domain */ template void @@ -149,8 +149,8 @@ constructRangeBandpassBoxcar(std::valarray subBandCenterFrequencies, int fft_size, std::valarray>& _filter1D) { - // construct a boxcar bandpass filter in frequency domian - // which may have several bands defined by centerferquencies and + // construct a boxcar bandpass filter in frequency domian + // which may have several bands defined by centerferquencies and // subBandBandwidths for (size_t i = 0; i subBandCenterFrequencies, double fH = subBandCenterFrequencies[i] + subBandBandwidths[i]/2; //index of frequencies for fL and fH - int indL; - indexOfFrequency(dt, fft_size, fL, indL); + int indL; + indexOfFrequency(dt, fft_size, fL, indL); int indH; indexOfFrequency(dt, fft_size, fH, indH); std::cout << "fL: "<< fL << " , fH: " << fH << " indL: " << indL << " , indH: " << indH << std::endl; @@ -202,8 +202,8 @@ constructRangeBandpassCosine(std::valarray subBandCenterFrequencies, std::valarray>& _filter1D) { - const double norm = 1.0; - + const double norm = 1.0; + for (size_t i = 0; i & refDoppler, // Transition region } else if (freq > (0.5 * bandwidth - df) && freq <= (0.5 * bandwidth + df)) { - _filter[i*ncols+j] = std::complex(norm * 0.5 * - (1.0 + std::cos(M_PI / (bandwidth*beta) * + _filter[i*ncols+j] = std::complex(norm * 0.5 * + (1.0 + std::cos(M_PI / (bandwidth*beta) * (freq - 0.5 * (1.0 - beta) * bandwidth))), 0.0); // Stop band @@ -311,7 +311,7 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, /** * @param[in] signal a block of data to filter. -* @param[in] spectrum of the block of the data +* @param[in] spectrum of the block of the data */ template void @@ -321,13 +321,13 @@ filter(std::valarray> &signal, { _signal.forward(signal, spectrum); spectrum = spectrum*_filter; - _signal.inverse(spectrum, signal); + _signal.inverse(spectrum, signal); } /** * @param[in] N length of the signal * @param[in] dt sampling interval of the signal - * @param[out] freq output vector of the frequencies + * @param[out] freq output vector of the frequencies */ void isce3::signal:: @@ -362,7 +362,7 @@ void isce3::signal::Filter:: indexOfFrequency(double dt, int N, double f, int &n) // deterrmine the index (n) of a given frequency f -// dt: sampling rate, +// dt: sampling rate, // N: length of a signal // f: frequency of interest // Assumption: for indices 0 to (N-1)/2, frequency is positive From e7bab5e700dbc7f49bc1d24f4f25a4597cdae6df Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 9 Oct 2023 21:11:14 +0000 Subject: [PATCH 003/106] crossmul pybinding for the range filter --- python/extensions/pybind_isce3/signal/Crossmul.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/python/extensions/pybind_isce3/signal/Crossmul.cpp b/python/extensions/pybind_isce3/signal/Crossmul.cpp index 700ab6796..7846b3403 100644 --- a/python/extensions/pybind_isce3/signal/Crossmul.cpp +++ b/python/extensions/pybind_isce3/signal/Crossmul.cpp @@ -58,6 +58,15 @@ void addbinding(py::class_ & pyCrossmul) .def_property("range_pixel_spacing", py::overload_cast<>(&Crossmul::rangePixelSpacing, py::const_), py::overload_cast(&Crossmul::rangePixelSpacing)) + .def_property("do_common_range_band_filter", + py::overload_cast<>(&Crossmul::doCommonRangeBandFilter, py::const_), + py::overload_cast(&Crossmul::doCommonRangeBandFilter)) + .def_property("range_sampling_frequency", + py::overload_cast<>(&Crossmul::rangeSamplingFrequency, py::const_), + py::overload_cast(&Crossmul::rangeSamplingFrequency)) + .def_property("range_bandwidth", + py::overload_cast<>(&Crossmul::rangeBandwidth, py::const_), + py::overload_cast(&Crossmul::rangeBandwidth)) .def_property("wavelength", py::overload_cast<>(&Crossmul::wavelength, py::const_), py::overload_cast(&Crossmul::wavelength)) From 09b2314069435f534945bbabdb4dd27e75fa4212 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 10 Oct 2023 00:25:44 +0000 Subject: [PATCH 004/106] add the range band filter --- .vscode/settings.json | 66 ++++++++++++++++++- cxx/isce3/signal/Crossmul.cpp | 66 ++++++++++++------- cxx/isce3/signal/Crossmul.h | 13 +++- cxx/isce3/signal/Crossmul.icc | 9 ++- cxx/isce3/signal/Filter.cpp | 3 +- .../pybind_isce3/signal/Crossmul.cpp | 6 ++ python/packages/nisar/workflows/crossmul.py | 20 +++++- .../nisar/workflows/crossmul_runconfig.py | 4 +- 8 files changed, 155 insertions(+), 32 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 801f50371..3f98ec367 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,69 @@ { "files.associations": { - "*.icc": "cpp" + "*.icc": "cpp", + "complex": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "condition_variable": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "set": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "valarray": "cpp", + "variant": "cpp" } } \ No newline at end of file diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index a714fd570..cafb55259 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -128,26 +128,34 @@ rangeCommonBandFilter(std::valarray> &refSlc, rngFilter.constructRangeBandpassFilter(_rangeSamplingFrequency, filterCenterFrequency, filterBandwidth, + refSlc, + refSpectrum, ncols, blockLength, filterType); - - // low pass filter the ref and sec slc + // low pass filter the ref slc rngFilter.filter(refSlc, refSpectrum); + + // low band pass the sec slc + rngFilter.constructRangeBandpassFilter(_rangeSamplingFrequency, + filterCenterFrequency, + filterBandwidth, + secSlc, + secSpectrum, + ncols, + blockLength, + filterType); rngFilter.filter(secSlc, secSpectrum); - // add/remove half geometrical phase to/from reference and secondary SLCs + // restore the original phase without the geometry phase + // in case other steps will use the original phase #pragma omp parallel for for (size_t i = 0; i < vectorLength; ++i) { - - // Half phase due to baseline separation obtained from range difference - // from reference and secondary antennas to the target (i.e., range - // offset derived from geometrical coregistration) - double halfPhase = std::arg(geometryIfgram[i]) / 2.0; + double phase = std::arg(geometryIfgram[i]); refSlc[i] *= - std::complex(std::cos(halfPhase), std::sin(halfPhase)); - secSlc[i] *= std::complex(std::cos(halfPhase), - -1 * std::sin(halfPhase)); + std::complex(std::cos(phase), std::sin(phase)); + secSlc[i] *= std::complex(std::cos(phase), + -1 * std::sin(phase)); } } @@ -203,15 +211,18 @@ crossmul(isce3::io::Raster& refSlcRaster, size_t nthreads = omp_thread_count(); - // Set flatten flag based range offset raster ptr value - bool flatten = rngOffsetRaster ? true : false; - //signal object for refSlc isce3::signal::Signal refSignal(nthreads); //signal object for secSlc isce3::signal::Signal secSignal(nthreads); + //signal object for geometryIfgram + isce3::signal::Signal geometryIfgramSignal(nthreads); + + //signal object for geometryIfgramConj + isce3::signal::Signal geometryIfgramConjSignal(nthreads); + // instantiate Looks used for multi-looking the interferogram isce3::signal::Looks looksObj; @@ -365,8 +376,19 @@ crossmul(isce3::io::Raster& refSlcRaster, if (_doCommonRangeBandFilter) { geometryIfgram.resize(spectrumSize); rangeFrequencies.resize(fft_size); - // TODO determine what this does and document + + // Compute the range frequency for each pixel fftfreq(1.0/_rangeSamplingFrequency, rangeFrequencies); + + geometryIfgramSignal.forwardRangeFFT(geometryIfgram, refSpectrum, + fft_size, linesPerBlock); + geometryIfgramSignal.inverseRangeFFT(refSpectrum, geometryIfgram, + fft_size, linesPerBlock); + + geometryIfgramConjSignal.forwardRangeFFT(geometryIfgramConj, secSpectrum, + fft_size, linesPerBlock); + geometryIfgramConjSignal.inverseRangeFFT(secSpectrum, geometryIfgramConj, + fft_size, linesPerBlock); } // loop over all blocks @@ -439,15 +461,16 @@ crossmul(isce3::io::Raster& refSlcRaster, } } - // Forward FFT to compute topo-dependent spectrum - refSignal.forward(geometryIfgramConj, refSpectrum); - refSignal.forward(geometryIfgram, secSpectrum); + // Forward FFT to compute topo-dependent spectrum to determine the + // frequency shift + geometryIfgramConjSignal.forward(geometryIfgramConj, refSpectrum); + geometryIfgramSignal.forward(geometryIfgram, secSpectrum); // Apply range common band filter to ref and sec SLC + // and the resultant refSlc and secSlc have no topo phase removal rangeCommonBandFilter(refSlc, secSlc, geometryIfgram, geometryIfgramConj, refSpectrum, secSpectrum, rangeFrequencies, rangeFilter, blockRowsData, fft_size); - } // upsample the reference and secondary SLCs @@ -471,7 +494,7 @@ crossmul(isce3::io::Raster& refSlcRaster, } } - if (flatten) { + if (_doFlatten) { // Read range offsets std::valarray offsetLine(ncols); for (size_t line = 0; line < blockRowsData; ++line) { @@ -485,7 +508,6 @@ crossmul(isce3::io::Raster& refSlcRaster, double phase = 4.0*M_PI*_rangePixelSpacing*rngOffset[line*ncols+col]/_wavelength; geometryIfgramConj[line*fft_size + col] = std::complex (std::cos(phase), -1.0*std::sin(phase)); - } } } @@ -500,7 +522,7 @@ crossmul(isce3::io::Raster& refSlcRaster, sum += ifgramUpsampled[line*(ncols*_oversampleFactor) + j + col*_oversampleFactor]; ifgram[line*ncols + col] = sum/ov; - if (flatten) + if (_doFlatten) ifgram[line*ncols + col] *= geometryIfgramConj[line*fft_size + col]; } } diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 9edea5e70..f7c79cc95 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -103,6 +103,14 @@ class isce3::signal::Crossmul { inline bool doCommonRangeBandFilter() const { return _doCommonRangeBandFilter; } + /** Set flatten flag */ + inline void doFlatten(bool doFlatten) { + _doFlatten = doFlatten; } + + /** Get flatten flag */ + inline bool doFlatten() const { + return _doFlatten; } + /** Set pulse repetition frequency (PRF) */ inline void prf(double prf) { _prf = prf; } @@ -181,6 +189,9 @@ class isce3::signal::Crossmul { bool _multiLookEnabled = false; + // Flag for topo phase removal + bool _doFlatten = false; + // Flag for common azimuth band filtering bool _doCommonAzimuthBandFilter = false; @@ -208,8 +219,6 @@ class isce3::signal::Crossmul { // upsampling factor size_t _oversampleFactor = 1; - - }; // Get inline implementations for Crossmul diff --git a/cxx/isce3/signal/Crossmul.icc b/cxx/isce3/signal/Crossmul.icc index 9f30e50dc..08e64ab2c 100644 --- a/cxx/isce3/signal/Crossmul.icc +++ b/cxx/isce3/signal/Crossmul.icc @@ -99,6 +99,9 @@ rangeFrequencyShift(std::valarray> &refSpectrum, // index of the max of secAvgSpectrum size_t idx2; + // the index for the frequency shift + size_t idx; + // get the index of the max of refAvgSpectrum getPeakIndex(refAvgSpectrum, idx1); @@ -107,9 +110,11 @@ rangeFrequencyShift(std::valarray> &refSpectrum, std::cout << "idx1, idx2: "<< idx1 << " , " << idx2 << std::endl; - // frequency shift is the difference of the two peaks - frequencyShift = rangeFrequencies[idx1] - rangeFrequencies[idx2]; + // use the smallest idx to determine the frequency shift + idx = std::min(idx1, idx2); + // frequency shift is the difference of the two peaks + frequencyShift = 2.0 * rangeFrequencies[idx]; } /**@param[in] data a vector to be evaluated for the index of its maximum diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 2dcc8fd7b..300483e8a 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -129,7 +129,6 @@ constructRangeBandpassFilter(double rangeSamplingFrequency, _filter[line*fft_size+col] = _filter1D[col] / norm; } } - } @@ -268,7 +267,7 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, // Construct vector of frequencies std::valarray frequency(fft_size); fftfreq(1.0/prf, frequency); - + // Loop over range bins for (int j = 0; j < ncols; ++j) { // Compute center frequency of common band diff --git a/python/extensions/pybind_isce3/signal/Crossmul.cpp b/python/extensions/pybind_isce3/signal/Crossmul.cpp index 7846b3403..318733de7 100644 --- a/python/extensions/pybind_isce3/signal/Crossmul.cpp +++ b/python/extensions/pybind_isce3/signal/Crossmul.cpp @@ -61,6 +61,12 @@ void addbinding(py::class_ & pyCrossmul) .def_property("do_common_range_band_filter", py::overload_cast<>(&Crossmul::doCommonRangeBandFilter, py::const_), py::overload_cast(&Crossmul::doCommonRangeBandFilter)) + .def_property("do_common_azimuth_band_filter", + py::overload_cast<>(&Crossmul::doCommonAzimuthBandFilter, py::const_), + py::overload_cast(&Crossmul::doCommonAzimuthBandFilter)) + .def_property("do_flatten", + py::overload_cast<>(&Crossmul::doFlatten, py::const_), + py::overload_cast(&Crossmul::doFlatten)) .def_property("range_sampling_frequency", py::overload_cast<>(&Crossmul::rangeSamplingFrequency, py::const_), py::overload_cast(&Crossmul::rangeSamplingFrequency)) diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index 29ed9e0af..b7b4c040d 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -32,6 +32,8 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', crossmul_params = cfg['processing']['crossmul'] scratch_path = pathlib.Path(cfg['product_path_group']['scratch_path']) flatten = crossmul_params['flatten'] + do_common_range_band_filter = crossmul_params['common_band_range_filter'] + lines_per_block = crossmul_params['lines_per_block'] if rg_looks == None: @@ -39,7 +41,7 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', if az_looks == None: az_looks = crossmul_params['azimuth_looks'] - if flatten: + if flatten or do_common_range_band_filter: flatten_path = crossmul_params['flatten_path'] if output_hdf5 is None: @@ -63,6 +65,13 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', crossmul = isce3.cuda.signal.Crossmul() else: crossmul = isce3.signal.Crossmul() + # do common range band filter + crossmul.do_common_range_band_filter =\ + do_common_range_band_filter + # do common azimuth band filter + crossmul.do_common_azimuth_band_filter = False + # do the flatten + crossmul.do_flatten = flatten crossmul.range_looks = rg_looks crossmul.az_looks = az_looks @@ -98,8 +107,15 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', crossmul.range_pixel_spacing = rdr_grid.range_pixel_spacing crossmul.wavelength = rdr_grid.wavelength + # CPU version + # TODO: Add those parameters for GPU + if not use_gpu: + crossmul.range_sampling_frequency = \ + 1.0 / (crossmul.range_pixel_spacing*2.0/isce3.core.speed_of_light) + crossmul.range_bandwidth = ref_slc.getSwathMetadata(freq).processed_range_bandwidth + # enable/disable flatten accordingly - if flatten: + if flatten or do_common_range_band_filter: # set frequency dependent range offset raster flatten_raster = isce3.io.Raster( f'{flatten_path}/geo2rdr/freq{freq}/range.off') diff --git a/python/packages/nisar/workflows/crossmul_runconfig.py b/python/packages/nisar/workflows/crossmul_runconfig.py index 8a9ab9a27..98c53f312 100644 --- a/python/packages/nisar/workflows/crossmul_runconfig.py +++ b/python/packages/nisar/workflows/crossmul_runconfig.py @@ -62,7 +62,9 @@ def yaml_check(self, resample_type): # flatten defaults to bool True # flatten_path defaults to scratch_path flatten = crossmul_cfg['flatten'] - if flatten: + do_common_band_filter = crossmul_cfg['common_band_range_filter'] + + if flatten or do_common_band_filter: if 'flatten_path' in crossmul_cfg: flatten_path = crossmul_cfg['flatten_path'] else: From 43dafeeca73a6d301bde78548820890c31be3898 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 10 Oct 2023 00:30:28 +0000 Subject: [PATCH 005/106] formats --- python/packages/nisar/workflows/crossmul.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index b7b4c040d..12a65c0b5 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -112,7 +112,8 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', if not use_gpu: crossmul.range_sampling_frequency = \ 1.0 / (crossmul.range_pixel_spacing*2.0/isce3.core.speed_of_light) - crossmul.range_bandwidth = ref_slc.getSwathMetadata(freq).processed_range_bandwidth + crossmul.range_bandwidth = \ + ref_slc.getSwathMetadata(freq).processed_range_bandwidth # enable/disable flatten accordingly if flatten or do_common_range_band_filter: From c0587a402f22c9cd52d7486021a3bb5b725c6e70 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 10 Oct 2023 23:19:16 +0000 Subject: [PATCH 006/106] add azimuth common band fitler with cosine filter --- cxx/isce3/signal/Crossmul.cpp | 57 +++++++----- cxx/isce3/signal/Crossmul.h | 19 ++-- cxx/isce3/signal/Crossmul.icc | 3 + cxx/isce3/signal/Filter.cpp | 93 +++++++++++++++++++ cxx/isce3/signal/Filter.h | 13 +++ .../pybind_isce3/signal/Crossmul.cpp | 9 ++ python/packages/nisar/workflows/crossmul.py | 10 +- 7 files changed, 167 insertions(+), 37 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index cafb55259..6c6a514f8 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -59,7 +59,7 @@ void lookdownShiftImpact(size_t oversample, size_t fft_size, size_t blockRows, // Utility function to get number of OpenMP threads // (gcc sometimes has problems with omp_get_num_threads) size_t omp_thread_count() { - // may use the omp_get_num_procs() + // may use the omp_get_num_procs()? size_t n = 0; #pragma omp parallel reduction(+:n) n += 1; @@ -265,7 +265,7 @@ crossmul(isce3::io::Raster& refSlcRaster, std::valarray> secSlc(spectrumSize); // storage for a block of range offsets - std::valarray rngOffset(ncols*linesPerBlock); + std::valarray rngOffset(spectrumSize); // storage for a simulated interferogram which its phase is the // interferometric phase due to the imaging geometry: @@ -361,16 +361,12 @@ crossmul(isce3::io::Raster& refSlcRaster, // Declare valarray for azimuth spectrum used by filter std::valarray> refAzimuthSpectrum; + std::valarray> secAzimuthSpectrum; if (_doCommonAzimuthBandFilter) { // Allocate storage for azimuth spectrum refAzimuthSpectrum.resize(spectrumSize); - - // Construct azimuth common band filter for a block of data - azimuthFilter.constructAzimuthCommonbandFilter( - _refDoppler, _secDoppler, _commonAzimuthBandwidth, - _prf, _beta, refSlc, refAzimuthSpectrum, fft_size, - linesPerBlock); + secAzimuthSpectrum.resize(spectrumSize); } if (_doCommonRangeBandFilter) { @@ -380,6 +376,7 @@ crossmul(isce3::io::Raster& refSlcRaster, // Compute the range frequency for each pixel fftfreq(1.0/_rangeSamplingFrequency, rangeFrequencies); + // Construct the FFTW plan for both geometryIfgram and its conjugation geometryIfgramSignal.forwardRangeFFT(geometryIfgram, refSpectrum, fft_size, linesPerBlock); geometryIfgramSignal.inverseRangeFFT(refSpectrum, geometryIfgram, @@ -425,10 +422,34 @@ crossmul(isce3::io::Raster& refSlcRaster, secSlc[std::slice(line*fft_size, ncols, 1)] = dataLine; } + // load the range offsets that are required by the flatten, + // common range and azimuth filters + if (_doFlatten || _doCommonAzimuthBandFilter || _doCommonRangeBandFilter) { + std::valarray offsetLine(ncols); + for (size_t line = 0; line < blockRowsData; ++line) { + rngOffsetRaster->getLine(offsetLine, rowStart + line); + rngOffset[std::slice(line*fft_size, ncols, 1)] = offsetLine; + } + } + //common azimuth band-pass filter the reference and secondary SLCs if (_doCommonAzimuthBandFilter) { + // Construct azimuth common band filter for a block of data + azimuthFilter.constructAzimuthCommonbandFilter( + _refDoppler, _secDoppler, rngOffset, + _azimuthBandwidth, + _prf, _beta, refSlc, refAzimuthSpectrum, fft_size, + linesPerBlock, true); azimuthFilter.filter(refSlc, refAzimuthSpectrum); - azimuthFilter.filter(secSlc, refAzimuthSpectrum); + + // Construct azimuth common band filter for a block of data + azimuthFilter.constructAzimuthCommonbandFilter( + _refDoppler, _secDoppler, rngOffset, + _azimuthBandwidth, + _prf, _beta, secSlc, secAzimuthSpectrum, fft_size, + linesPerBlock, false); + + azimuthFilter.filter(secSlc, secAzimuthSpectrum); } // common range band-pass filtering @@ -439,19 +460,12 @@ crossmul(isce3::io::Raster& refSlcRaster, std::cout << " - range pixel spacing: " << _rangePixelSpacing << std::endl; std::cout << " - wavelength: " << _wavelength << std::endl; - // Read range offsets - std::valarray offsetLine(ncols); - for (size_t line = 0; line < blockRowsData; ++line) { - rngOffsetRaster->getLine(offsetLine, rowStart + line); - rngOffset[std::slice(line*ncols, ncols, 1)] = offsetLine; - } - // Convert range offset from meters to complex phase #pragma omp parallel for for (size_t line = 0; line < blockRowsData; ++line) { for (size_t col = 0; col < ncols; ++col) { double phase = 4.0 * M_PI - * _rangePixelSpacing*rngOffset[line*ncols+col] + * _rangePixelSpacing*rngOffset[line*fft_size+col] / _wavelength; geometryIfgram[line*fft_size + col] = @@ -495,17 +509,10 @@ crossmul(isce3::io::Raster& refSlcRaster, } if (_doFlatten) { - // Read range offsets - std::valarray offsetLine(ncols); - for (size_t line = 0; line < blockRowsData; ++line) { - rngOffsetRaster->getLine(offsetLine, rowStart + line); - rngOffset[std::slice(line*ncols, ncols, 1)] = offsetLine; - } - #pragma omp parallel for for (size_t line = 0; line < blockRowsData; ++line) { for (size_t col = 0; col < ncols; ++col) { - double phase = 4.0*M_PI*_rangePixelSpacing*rngOffset[line*ncols+col]/_wavelength; + double phase = 4.0*M_PI*_rangePixelSpacing*rngOffset[line*fft_size+col]/_wavelength; geometryIfgramConj[line*fft_size + col] = std::complex (std::cos(phase), -1.0*std::sin(phase)); } diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index f7c79cc95..4d2afe2dd 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -81,13 +81,13 @@ class isce3::signal::Crossmul { inline bool doCommonAzimuthBandFilter() const { return _doCommonAzimuthBandFilter; } - /** Set azimuth common bandwidth */ - inline void commonAzimuthBandwidth(double azBandwidth) { - _commonAzimuthBandwidth = azBandwidth; } + /** Set azimuth bandwidth */ + inline void azimuthBandwidth(double azBandwidth) { + _azimuthBandwidth = azBandwidth; } - /** Get azimuth common bandwidth */ - inline double commonAzimuthBandwidth() const { - return _commonAzimuthBandwidth; } + /** Get azimuth bandwidth */ + inline double azimuthBandwidth() const { + return _azimuthBandwidth; } /** Set beta parameter for the azimuth common band filter */ inline void beta(double beta) { _beta = beta; } @@ -195,12 +195,11 @@ class isce3::signal::Crossmul { // Flag for common azimuth band filtering bool _doCommonAzimuthBandFilter = false; - // Azimuth common bandwidth - // TODO make a part of constructor? - double _commonAzimuthBandwidth; + // Azimuth bandwidth + double _azimuthBandwidth; // Beta parameter for constructing common azimuth band filter - double _beta; + double _beta = 0.25; // Flag for common range band filtering bool _doCommonRangeBandFilter = false; diff --git a/cxx/isce3/signal/Crossmul.icc b/cxx/isce3/signal/Crossmul.icc index 08e64ab2c..9df013e43 100644 --- a/cxx/isce3/signal/Crossmul.icc +++ b/cxx/isce3/signal/Crossmul.icc @@ -111,9 +111,12 @@ rangeFrequencyShift(std::valarray> &refSpectrum, std::cout << "idx1, idx2: "<< idx1 << " , " << idx2 << std::endl; // use the smallest idx to determine the frequency shift + // this is because their peaks can lie at two sides if + // the fftshift operation is not performed. idx = std::min(idx1, idx2); // frequency shift is the difference of the two peaks + // i.e., two times of the offset of the one peak frequencyShift = 2.0 * rangeFrequencies[idx]; } diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 300483e8a..5afcbc10c 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -228,6 +228,97 @@ constructRangeBandpassCosine(std::valarray subBandCenterFrequencies, } } +/** +* @param[in] refDoppler Doppler LUT1d of the reference SLC +* @param[in] secDoppler Doppler LUT1d of the secondary SLC +* @param[in] rangeOffsets Range pixel offsets between secondary and reference SLC (i.e., secondary - reference) +* @param[in] bandwidth common bandwidth in azimuth +* @param[in] prf pulse repetition frequency +* @param[in] beta parameter for raised cosine filter +* @param[in] signal a block of data to filter +* @param[in] spectrum of the block of data +* @param[in] ncols number of columns of the block of data +* @param[in] nrows number of rows of the block of data +* @param[in] isReferenceSLCFilter filter on the reference SLC, default is true. +*/ +template +void +isce3::signal::Filter:: +constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, + const isce3::core::LUT1d & secDoppler, + std::valarray &rangeOffsets, + double bandwidth, + double prf, + double beta, + std::valarray> &signal, + std::valarray> &spectrum, + size_t ncols, + size_t nrows, + bool isReferenceSLCFilter) +{ + _filter.resize(ncols*nrows); + + // Pedestal-dependent frequency offset for transition region + const double df = 0.5 * bandwidth * beta; + // Compute normalization factor for preserving average power between input + // data and filtered data. Assumes both filter and input signal have flat + // spectra in the passband. + //const double norm = std::sqrt(input_BW / BW); + const double norm = 1.0; + + // we probably need to give next power of 2 ??? + int fft_size = nrows; + // Construct vector of frequencies + std::valarray frequency(fft_size); + fftfreq(1.0/prf, frequency); + + // Loop over range bins + for (int j = 0; j < ncols; ++j) { + // Compute center frequency of common band + // I think we need the range offsets here to restore the fDC + // for the secondary doppler since it is the resampled RSLC + // middle frequency for the reference SLC + double fmid = -0.5 * (refDoppler.eval(j) - + secDoppler.eval(j + rangeOffsets[j])); + + // for seconary SLC filter + if (!isReferenceSLCFilter) fmid *= -1; + + // Compute filter + for (size_t i = 0; i < frequency.size(); ++i) { + + // Get the absolute value of shifted frequency + const double freq = std::abs(frequency[i] - fmid); + + // Passband + if (freq <= (0.5 * bandwidth - df)) { + _filter[i*ncols+j] = std::complex(norm, 0.0); + + // Transition region + } else if (freq > (0.5 * bandwidth - df) && freq <= (0.5 * bandwidth + df)) { + _filter[i*ncols+j] = std::complex(norm * 0.5 * + (1.0 + std::cos(M_PI / (bandwidth*beta) * + (freq - 0.5 * (1.0 - beta) * bandwidth))), 0.0); + + // Stop band + } else { + _filter[i*ncols+j] = std::complex(0.0, 0.0); + } + } + } + + // Normalize the filter + const std::complex filtNorm(fft_size, fft_size); + for (int j = 0; j < ncols; ++j) { + for (size_t i = 0; i < frequency.size(); ++i) { + _filter[i*ncols+j] /= filtNorm; + } + } + + _signal.forwardAzimuthFFT(signal, spectrum, ncols, nrows); + _signal.inverseAzimuthFFT(spectrum, signal, ncols, nrows); +} + /** * @param[in] refDoppler Doppler LUT1d of the reference SLC * @param[in] secDoppler Doppler LUT1d of the secondary SLC @@ -271,6 +362,8 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, // Loop over range bins for (int j = 0; j < ncols; ++j) { // Compute center frequency of common band + // I think we need the range offsets here for the secondary doppler + // as here is the resampled secondary RSLC const double fmid = 0.5 * (refDoppler.eval(j) + secDoppler.eval(j)); // Compute filter diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index e321b48fa..1ed653573 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -90,6 +90,19 @@ class isce3::signal::Filter { size_t ncols, size_t nrows); + /** Construct azimuth common band filter with the doppler centroid compensation*/ + void constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, + const isce3::core::LUT1d & secDoppler, + std::valarray &rangeOffsets, + double bandwidth, + double prf, + double beta, + std::valarray> &signal, + std::valarray> &spectrum, + size_t ncols, + size_t nrows, + bool isReferenceSLCFilter = true); + /** Filter a signal in frequency domain*/ void filter(std::valarray> &signal, std::valarray> &spectrum); diff --git a/python/extensions/pybind_isce3/signal/Crossmul.cpp b/python/extensions/pybind_isce3/signal/Crossmul.cpp index 318733de7..b31091787 100644 --- a/python/extensions/pybind_isce3/signal/Crossmul.cpp +++ b/python/extensions/pybind_isce3/signal/Crossmul.cpp @@ -73,6 +73,15 @@ void addbinding(py::class_ & pyCrossmul) .def_property("range_bandwidth", py::overload_cast<>(&Crossmul::rangeBandwidth, py::const_), py::overload_cast(&Crossmul::rangeBandwidth)) + .def_property("azimuth_bandwidth", + py::overload_cast<>(&Crossmul::azimuthBandwidth, py::const_), + py::overload_cast(&Crossmul::azimuthBandwidth)) + .def_property("prf", + py::overload_cast<>(&Crossmul::prf, py::const_), + py::overload_cast(&Crossmul::prf)) + .def_property("beta", + py::overload_cast<>(&Crossmul::beta, py::const_), + py::overload_cast(&Crossmul::beta)) .def_property("wavelength", py::overload_cast<>(&Crossmul::wavelength, py::const_), py::overload_cast(&Crossmul::wavelength)) diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index 12a65c0b5..e878b09ee 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -33,6 +33,7 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', scratch_path = pathlib.Path(cfg['product_path_group']['scratch_path']) flatten = crossmul_params['flatten'] do_common_range_band_filter = crossmul_params['common_band_range_filter'] + do_common_azimuth_band_filter = crossmul_params['common_band_azimuth_filter'] lines_per_block = crossmul_params['lines_per_block'] @@ -66,10 +67,11 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', else: crossmul = isce3.signal.Crossmul() # do common range band filter - crossmul.do_common_range_band_filter =\ + crossmul.do_common_range_band_filter = \ do_common_range_band_filter # do common azimuth band filter - crossmul.do_common_azimuth_band_filter = False + crossmul.do_common_azimuth_band_filter = \ + do_common_azimuth_band_filter # do the flatten crossmul.do_flatten = flatten @@ -115,6 +117,10 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', crossmul.range_bandwidth = \ ref_slc.getSwathMetadata(freq).processed_range_bandwidth + crossmul.azimuth_bandwidth = ref_slc.getSwathMetadata(freq).processed_azimuth_bandwidth + crossmul.prf = rdr_grid.prf + crossmul.beta = 0.25 + # enable/disable flatten accordingly if flatten or do_common_range_band_filter: # set frequency dependent range offset raster From b8ee7072250383e3166bfc2d3f4c213eff093a25 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 11 Oct 2023 18:09:14 +0000 Subject: [PATCH 007/106] add the range kaiser filter --- cxx/isce3/signal/Crossmul.cpp | 3 +- cxx/isce3/signal/Crossmul.icc | 2 +- cxx/isce3/signal/Filter.cpp | 77 ++++++++++++++++++++++++++++++++++- cxx/isce3/signal/Filter.h | 11 +++++ 4 files changed, 90 insertions(+), 3 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 6c6a514f8..37a9b8803 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -121,7 +121,8 @@ rangeCommonBandFilter(std::valarray> &refSlc, // bandwidth of (W - frequency shift) std::valarray filterCenterFrequency{0.0}; std::valarray filterBandwidth{_rangeBandwidth - fabs(frequencyShift)}; - std::string filterType = "cosine"; + + std::string filterType = "kaiser"; // Contruct the low pass filter for this block. This filter is // common for both SLCs diff --git a/cxx/isce3/signal/Crossmul.icc b/cxx/isce3/signal/Crossmul.icc index 9df013e43..4d425477d 100644 --- a/cxx/isce3/signal/Crossmul.icc +++ b/cxx/isce3/signal/Crossmul.icc @@ -108,7 +108,7 @@ rangeFrequencyShift(std::valarray> &refSpectrum, // get the index of the max of secAvgSpectrum getPeakIndex(secAvgSpectrum, idx2); - std::cout << "idx1, idx2: "<< idx1 << " , " << idx2 << std::endl; + std::cout << "idx1, idx2, columns: "<< idx1 << " , " << idx2 << ", " << fft_size < subBandCenterFrequencies, } } +/** + * @param[in] subBandCenterFrequencies a vector of center frequencies for each band + * @param[in] subBandBandwidths a vector of bandwidths for each band + * @param[in] dt samplig rate of the signal + * @param[in] fft_size length of the spectrum + * @param[in] frequency a vector of frequencies + * @param[in] beta parameter for the kaiser filter (normally set 2.5) + * @param[out] _filter1D one dimensional boxcar bandpass filter in frequency domain + */ +template +void +isce3::signal::Filter:: +constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, + std::valarray subBandBandwidths, + double dt, + int fft_size, + std::valarray& frequency, + double beta, + std::valarray>& _filter1D) +{ + + // construct a kaiser bandpass filter in frequency domian + // which may have several bands defined by centerferquencies and + // subBandBandwidths + for (size_t i = 0; i=0){ + for (size_t ind = indL; ind < fft_size; ++ind){ + double fre = fL + (ind - indL) / (dt * fft_size); + double tmp = 2.0 * fre * dt; + double kaiserCoefficent = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); + _filter1D[ind] = std::complex(kaiserCoefficent/bessel_i0_beta, 0.0); + } + for (size_t ind = 0; ind < indH; ++ind){ + double fre = ind / (dt * fft_size); + double tmp = 2.0 * fre * dt; + double kaiserCoefficent = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); + _filter1D[ind] = std::complex(kaiserCoefficent/bessel_i0_beta, 0.0); + } + + }else{ + for (size_t ind = indL; ind < indH; ++ind){ + double fre = (ind - 0.5 * (indL + indH)) / (dt * fft_size); + double tmp = 2.0 * fre * dt; + double kaiserCoefficent = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); + _filter1D[ind] = std::complex(kaiserCoefficent/bessel_i0_beta, 0.0); + } + } + } +} + /** * @param[in] refDoppler Doppler LUT1d of the reference SLC * @param[in] secDoppler Doppler LUT1d of the secondary SLC diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index 1ed653573..4cd79607e 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -15,6 +15,7 @@ #include #include #include +#include #include "Signal.h" // Declaration @@ -70,6 +71,7 @@ class isce3::signal::Filter { int fft_size, std::valarray> &_filter1D); + /** Construct a cosine range band-pass filter for multiple bands*/ void constructRangeBandpassCosine(std::valarray subBandCenterFrequencies, std::valarray subBandBandwidths, double dt, @@ -77,6 +79,15 @@ class isce3::signal::Filter { double beta, std::valarray>& _filter1D); + /** Construct a kaiser range band-pass filter for multiple bands*/ + void constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, + std::valarray subBandBandwidths, + double dt, + int fft_size, + std::valarray& frequency, + double beta, + std::valarray>& _filter1D); + //T constructRangeCommonbandFilter(); /** Construct azimuth common band filter*/ From bc35b200f9f00e6dd09891cc71d99fbd79f0be7b Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 11 Oct 2023 19:11:02 +0000 Subject: [PATCH 008/106] add azimuth kaiser filter --- cxx/isce3/signal/Crossmul.cpp | 16 ++-- cxx/isce3/signal/Filter.cpp | 119 +++++++++++++++++++----------- cxx/isce3/signal/Filter.h | 26 +++++-- tests/cxx/isce3/signal/filter.cpp | 23 +++--- 4 files changed, 119 insertions(+), 65 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 37a9b8803..f7dcc8780 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -122,7 +122,7 @@ rangeCommonBandFilter(std::valarray> &refSlc, std::valarray filterCenterFrequency{0.0}; std::valarray filterBandwidth{_rangeBandwidth - fabs(frequencyShift)}; - std::string filterType = "kaiser"; + std::string filterType = "cosine"; // Contruct the low pass filter for this block. This filter is // common for both SLCs @@ -435,20 +435,22 @@ crossmul(isce3::io::Raster& refSlcRaster, //common azimuth band-pass filter the reference and secondary SLCs if (_doCommonAzimuthBandFilter) { - // Construct azimuth common band filter for a block of data + + std::string filterType = "kaiser"; + // Construct azimuth common band filter for a block of data of the reference azimuthFilter.constructAzimuthCommonbandFilter( _refDoppler, _secDoppler, rngOffset, _azimuthBandwidth, - _prf, _beta, refSlc, refAzimuthSpectrum, fft_size, - linesPerBlock, true); + _prf, 2.5, refSlc, refAzimuthSpectrum, fft_size, + linesPerBlock, true, filterType); azimuthFilter.filter(refSlc, refAzimuthSpectrum); - // Construct azimuth common band filter for a block of data + // Construct azimuth common band filter for a block of data of the secondary azimuthFilter.constructAzimuthCommonbandFilter( _refDoppler, _secDoppler, rngOffset, _azimuthBandwidth, - _prf, _beta, secSlc, secAzimuthSpectrum, fft_size, - linesPerBlock, false); + _prf, 2.5, secSlc, secAzimuthSpectrum, fft_size, + linesPerBlock, false, filterType); azimuthFilter.filter(secSlc, secAzimuthSpectrum); } diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 720efce48..2f43f15f7 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -309,7 +309,7 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, * @param[in] rangeOffsets Range pixel offsets between secondary and reference SLC (i.e., secondary - reference) * @param[in] bandwidth common bandwidth in azimuth * @param[in] prf pulse repetition frequency -* @param[in] beta parameter for raised cosine filter +* @param[in] beta parameter for raised cosine filter (0.25) or for the kaiser filter (2.5) * @param[in] signal a block of data to filter * @param[in] spectrum of the block of data * @param[in] ncols number of columns of the block of data @@ -320,6 +320,57 @@ template void isce3::signal::Filter:: constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, + const isce3::core::LUT1d & secDoppler, + std::valarray &rangeOffsets, + double bandwidth, + double prf, + double beta, + std::valarray> &signal, + std::valarray> &spectrum, + size_t ncols, + size_t nrows, + bool isReferenceSLCFilter, + std::string filterType) +{ + if (filterType=="cosine"){ + constructAzimuthCommonbandCosineFilter( + refDoppler, + secDoppler, + rangeOffsets, + bandwidth, + prf, beta, signal, spectrum, + ncols, nrows, isReferenceSLCFilter); + + } else if (filterType=="kaiser"){ + constructAzimuthCommonbandKaiserFilter( + refDoppler, + secDoppler, + rangeOffsets, + bandwidth, + prf, beta, signal, spectrum, + ncols, nrows, isReferenceSLCFilter); + } else{ + std::cout << filterType << " filter has not been implemented" << std::endl; + } +} + +/** +* @param[in] refDoppler Doppler LUT1d of the reference SLC +* @param[in] secDoppler Doppler LUT1d of the secondary SLC +* @param[in] rangeOffsets Range pixel offsets between secondary and reference SLC (i.e., secondary - reference) +* @param[in] bandwidth common bandwidth in azimuth +* @param[in] prf pulse repetition frequency +* @param[in] beta parameter for raised cosine filter +* @param[in] signal a block of data to filter +* @param[in] spectrum of the block of data +* @param[in] ncols number of columns of the block of data +* @param[in] nrows number of rows of the block of data +* @param[in] isReferenceSLCFilter filter on the reference SLC, default is true. +*/ +template +void +isce3::signal::Filter:: +constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDoppler, const isce3::core::LUT1d & secDoppler, std::valarray &rangeOffsets, double bandwidth, @@ -356,7 +407,7 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, double fmid = -0.5 * (refDoppler.eval(j) - secDoppler.eval(j + rangeOffsets[j])); - // for seconary SLC filter + // for secondary SLC filter if (!isReferenceSLCFilter) fmid *= -1; // Compute filter @@ -397,78 +448,61 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, /** * @param[in] refDoppler Doppler LUT1d of the reference SLC * @param[in] secDoppler Doppler LUT1d of the secondary SLC +* @param[in] rangeOffsets Range pixel offsets between secondary and reference SLC (i.e., secondary - reference) * @param[in] bandwidth common bandwidth in azimuth * @param[in] prf pulse repetition frequency -* @param[in] beta parameter for raised cosine filter +* @param[in] beta parameter for kaiser filter * @param[in] signal a block of data to filter * @param[in] spectrum of the block of data * @param[in] ncols number of columns of the block of data * @param[in] nrows number of rows of the block of data +* @param[in] isReferenceSLCFilter filter on the reference SLC, default is true. */ template void isce3::signal::Filter:: -constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, +constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDoppler, const isce3::core::LUT1d & secDoppler, + std::valarray &rangeOffsets, double bandwidth, double prf, double beta, std::valarray> &signal, std::valarray> &spectrum, size_t ncols, - size_t nrows) + size_t nrows, + bool isReferenceSLCFilter) { _filter.resize(ncols*nrows); - // Pedestal-dependent frequency offset for transition region - const double df = 0.5 * bandwidth * beta; - // Compute normalization factor for preserving average power between input - // data and filtered data. Assumes both filter and input signal have flat - // spectra in the passband. - //const double norm = std::sqrt(input_BW / BW); - const double norm = 1.0; - // we probably need to give next power of 2 ??? int fft_size = nrows; // Construct vector of frequencies std::valarray frequency(fft_size); fftfreq(1.0/prf, frequency); + // bessel_i0 of beta + double bessel_i0_beta = isce3::math::bessel_i0(beta); + // Loop over range bins for (int j = 0; j < ncols; ++j) { // Compute center frequency of common band - // I think we need the range offsets here for the secondary doppler - // as here is the resampled secondary RSLC - const double fmid = 0.5 * (refDoppler.eval(j) + secDoppler.eval(j)); - - // Compute filter - for (size_t i = 0; i < frequency.size(); ++i) { - - // Get the absolute value of shifted frequency - const double freq = std::abs(frequency[i] - fmid); - - // Passband - if (freq <= (0.5 * bandwidth - df)) { - _filter[i*ncols+j] = std::complex(norm, 0.0); - - // Transition region - } else if (freq > (0.5 * bandwidth - df) && freq <= (0.5 * bandwidth + df)) { - _filter[i*ncols+j] = std::complex(norm * 0.5 * - (1.0 + std::cos(M_PI / (bandwidth*beta) * - (freq - 0.5 * (1.0 - beta) * bandwidth))), 0.0); + // I think we need the range offsets here to restore the fDC + // for the secondary doppler since it is the resampled RSLC + // frequency shift for the reference SLC + double fmid = -0.5 * (refDoppler.eval(j) - + secDoppler.eval(j + rangeOffsets[j])); - // Stop band - } else { - _filter[i*ncols+j] = std::complex(0.0, 0.0); - } - } - } + // for secondary SLC filter + if (!isReferenceSLCFilter) fmid *= -1; - // Normalize the filter - const std::complex filtNorm(fft_size, fft_size); - for (int j = 0; j < ncols; ++j) { + // Compute the filter for (size_t i = 0; i < frequency.size(); ++i) { - _filter[i*ncols+j] /= filtNorm; + + const double freq = frequency[i] - fmid; + double tmp = 2.0 * freq / prf; + double kaiserCoefficent = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); + _filter[i*ncols+j] = std::complex(kaiserCoefficent/bessel_i0_beta, 0.0); } } @@ -476,6 +510,7 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, _signal.inverseAzimuthFFT(spectrum, signal, ncols, nrows); } + /** * @param[in] signal a block of data to filter. * @param[in] spectrum of the block of the data diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index 4cd79607e..3563e9c44 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -32,7 +32,7 @@ class isce3::signal::Filter { ~Filter() {}; - /** constructs forward abd backward FFT plans for filtering a block of data in range direction. */ + /** constructs forward abd backward FFT plans for filtering a block of data in range direction. */ void initiateRangeFilter(std::valarray> &signal, std::valarray> &spectrum, size_t ncols, @@ -88,21 +88,35 @@ class isce3::signal::Filter { double beta, std::valarray>& _filter1D); - //T constructRangeCommonbandFilter(); - /** Construct azimuth common band filter*/ void constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, + const isce3::core::LUT1d & secDoppler, + std::valarray &rangeOffsets, + double bandwidth, + double prf, + double beta, + std::valarray> &signal, + std::valarray> &spectrum, + size_t ncols, + size_t nrows, + bool isReferenceSLCFilter, + std::string filterType); + + /** Construct azimuth common band cosine filter with the doppler centroid compensation*/ + void constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDoppler, const isce3::core::LUT1d & secDoppler, + std::valarray &rangeOffsets, double bandwidth, double prf, double beta, std::valarray> &signal, std::valarray> &spectrum, size_t ncols, - size_t nrows); + size_t nrows, + bool isReferenceSLCFilter = true); - /** Construct azimuth common band filter with the doppler centroid compensation*/ - void constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, + /** Construct azimuth common band kaiser filter with the doppler centroid compensation*/ + void constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDoppler, const isce3::core::LUT1d & secDoppler, std::valarray &rangeOffsets, double bandwidth, diff --git a/tests/cxx/isce3/signal/filter.cpp b/tests/cxx/isce3/signal/filter.cpp index 430a39518..44ef688aa 100644 --- a/tests/cxx/isce3/signal/filter.cpp +++ b/tests/cxx/isce3/signal/filter.cpp @@ -24,6 +24,8 @@ TEST(Filter, constructAzimuthCommonbandFilter) std::valarray> refSlc(ncols*blockRows); std::valarray> refSpectrum(nfft*blockRows); + std::valarray rangeOffsets(nfft*blockRows); + rangeOffsets = 0.0; // Get some metadata from an existing HDF5 file std::string h5file(TESTDATA_DIR "envisat.h5"); @@ -50,13 +52,14 @@ TEST(Filter, constructAzimuthCommonbandFilter) double commonAzimuthBandwidth = 1000.0; isce3::signal::Filter filter; - filter.constructAzimuthCommonbandFilter(dop1, - dop2, - commonAzimuthBandwidth, - prf, - beta, - refSlc, refSpectrum, - ncols, blockRows); + filter.constructAzimuthCommonbandCosineFilter(dop1, + dop2, + rangeOffsets, + commonAzimuthBandwidth, + prf, + beta, + refSlc, refSpectrum, + ncols, blockRows, true); filter.writeFilter(ncols, blockRows); } @@ -80,10 +83,10 @@ TEST(Filter, constructBoxcarRangeBandpassFilter) // get the range bandwidth double BW = swath.processedRangeBandwidth(); - + //The bands are specified by two vectors: // 1) a vector of center frequencies for each sub-band - std::valarray subBandCenterFrequencies{-3.0e6, 0.0, 3e6}; + std::valarray subBandCenterFrequencies{-3.0e6, 0.0, 3e6}; // 2) a vector of bandwidth of each sub-band std::valarray subBandBandwidths{2.0e6, 2.0e6, 2.0e6}; @@ -115,7 +118,7 @@ TEST(Filter, constructBoxcarRangeBandpassFilter) filterType); //filter.writeFilter(ncols, blockRows); - + } int main(int argc, char * argv[]) { From b30afb71d178425ad4fead013497b2c931c37ee0 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 11 Oct 2023 20:20:59 +0000 Subject: [PATCH 009/106] fix kaiser azimuth filter bug --- cxx/isce3/signal/Filter.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 2f43f15f7..ad0a1d7b5 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -474,7 +474,7 @@ constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDop bool isReferenceSLCFilter) { _filter.resize(ncols*nrows); - + _filter = std::complex(0.0, 0.0); // we probably need to give next power of 2 ??? int fft_size = nrows; // Construct vector of frequencies @@ -499,7 +499,12 @@ constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDop // Compute the filter for (size_t i = 0; i < frequency.size(); ++i) { - const double freq = frequency[i] - fmid; + double freq = frequency[i] - fmid; + + // make it circular + if (freq > prf/2.0) freq -= prf; + if (freq < -prf/2.0) freq += prf; + double tmp = 2.0 * freq / prf; double kaiserCoefficent = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); _filter[i*ncols+j] = std::complex(kaiserCoefficent/bessel_i0_beta, 0.0); From 9ac9fef36ff26f9cdde0cb990f34b87dfa61f619 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 11 Oct 2023 20:57:22 +0000 Subject: [PATCH 010/106] clean --- cxx/isce3/signal/Crossmul.cpp | 9 +++++---- cxx/isce3/signal/Crossmul.icc | 2 +- cxx/isce3/signal/Filter.cpp | 8 ++++++-- python/extensions/pybind_isce3/signal/Crossmul.cpp | 3 --- python/packages/nisar/workflows/crossmul.py | 1 - 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index f7dcc8780..c31e790ca 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -113,8 +113,8 @@ rangeCommonBandFilter(std::valarray> &refSlc, ncols, frequencyShift); - std::cout << "frequencyShift : "<< frequencyShift << std::endl; - std::cout << "range bandwidth: " << _rangeBandwidth << std::endl; + std::cout << " - rangeFrequencyShift : "<< frequencyShift << std::endl; + std::cout << " - range bandwidth: " << _rangeBandwidth << std::endl; // Since the spectrum of the ref and sec SLCs are already aligned, // we design the low-pass filter as a band-pass at zero frequency with @@ -437,11 +437,12 @@ crossmul(isce3::io::Raster& refSlcRaster, if (_doCommonAzimuthBandFilter) { std::string filterType = "kaiser"; + double beta = 2.5; // Construct azimuth common band filter for a block of data of the reference azimuthFilter.constructAzimuthCommonbandFilter( _refDoppler, _secDoppler, rngOffset, _azimuthBandwidth, - _prf, 2.5, refSlc, refAzimuthSpectrum, fft_size, + _prf, beta, refSlc, refAzimuthSpectrum, fft_size, linesPerBlock, true, filterType); azimuthFilter.filter(refSlc, refAzimuthSpectrum); @@ -449,7 +450,7 @@ crossmul(isce3::io::Raster& refSlcRaster, azimuthFilter.constructAzimuthCommonbandFilter( _refDoppler, _secDoppler, rngOffset, _azimuthBandwidth, - _prf, 2.5, secSlc, secAzimuthSpectrum, fft_size, + _prf, beta, secSlc, secAzimuthSpectrum, fft_size, linesPerBlock, false, filterType); azimuthFilter.filter(secSlc, secAzimuthSpectrum); diff --git a/cxx/isce3/signal/Crossmul.icc b/cxx/isce3/signal/Crossmul.icc index 4d425477d..1465d7cff 100644 --- a/cxx/isce3/signal/Crossmul.icc +++ b/cxx/isce3/signal/Crossmul.icc @@ -108,7 +108,7 @@ rangeFrequencyShift(std::valarray> &refSpectrum, // get the index of the max of secAvgSpectrum getPeakIndex(secAvgSpectrum, idx2); - std::cout << "idx1, idx2, columns: "<< idx1 << " , " << idx2 << ", " << fft_size < & refDop // bessel_i0 of beta double bessel_i0_beta = isce3::math::bessel_i0(beta); - + double meanDopFreqshifts = 0.0; // Loop over range bins for (int j = 0; j < ncols; ++j) { // Compute center frequency of common band @@ -496,7 +496,9 @@ constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDop // for secondary SLC filter if (!isReferenceSLCFilter) fmid *= -1; - // Compute the filter + meanDopFreqshifts += fmid; + + // Compute the filter centered at fmid for (size_t i = 0; i < frequency.size(); ++i) { double freq = frequency[i] - fmid; @@ -511,6 +513,8 @@ constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDop } } + std::cout << " - mean doppler centroid shift:" << meanDopFreqshifts/ncols << std::endl; + _signal.forwardAzimuthFFT(signal, spectrum, ncols, nrows); _signal.inverseAzimuthFFT(spectrum, signal, ncols, nrows); } diff --git a/python/extensions/pybind_isce3/signal/Crossmul.cpp b/python/extensions/pybind_isce3/signal/Crossmul.cpp index b31091787..c674af365 100644 --- a/python/extensions/pybind_isce3/signal/Crossmul.cpp +++ b/python/extensions/pybind_isce3/signal/Crossmul.cpp @@ -79,9 +79,6 @@ void addbinding(py::class_ & pyCrossmul) .def_property("prf", py::overload_cast<>(&Crossmul::prf, py::const_), py::overload_cast(&Crossmul::prf)) - .def_property("beta", - py::overload_cast<>(&Crossmul::beta, py::const_), - py::overload_cast(&Crossmul::beta)) .def_property("wavelength", py::overload_cast<>(&Crossmul::wavelength, py::const_), py::overload_cast(&Crossmul::wavelength)) diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index e878b09ee..d66eb81da 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -119,7 +119,6 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', crossmul.azimuth_bandwidth = ref_slc.getSwathMetadata(freq).processed_azimuth_bandwidth crossmul.prf = rdr_grid.prf - crossmul.beta = 0.25 # enable/disable flatten accordingly if flatten or do_common_range_band_filter: From fbda9ce8822060139f3ccda2a1bd5d134e3acb97 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 11 Oct 2023 21:00:39 +0000 Subject: [PATCH 011/106] clean croosmul.py --- python/packages/nisar/workflows/crossmul.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index d66eb81da..daab53618 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -110,18 +110,20 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', crossmul.wavelength = rdr_grid.wavelength # CPU version - # TODO: Add those parameters for GPU + # TODO: Add parameters to GPU implementation if not use_gpu: + # range sampling rate and bandwidth crossmul.range_sampling_frequency = \ 1.0 / (crossmul.range_pixel_spacing*2.0/isce3.core.speed_of_light) crossmul.range_bandwidth = \ ref_slc.getSwathMetadata(freq).processed_range_bandwidth - - crossmul.azimuth_bandwidth = ref_slc.getSwathMetadata(freq).processed_azimuth_bandwidth + # azimuth band width and PRF + crossmul.azimuth_bandwidth = \ + ref_slc.getSwathMetadata(freq).processed_azimuth_bandwidth crossmul.prf = rdr_grid.prf # enable/disable flatten accordingly - if flatten or do_common_range_band_filter: + if flatten or do_common_range_band_filter or do_common_azimuth_band_filter: # set frequency dependent range offset raster flatten_raster = isce3.io.Raster( f'{flatten_path}/geo2rdr/freq{freq}/range.off') From bf402561d221b92ff2efb8623533089d84e4b118 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 11 Oct 2023 21:10:48 +0000 Subject: [PATCH 012/106] delete vscode file --- .vscode/settings.json | 69 ------------------------------------------- 1 file changed, 69 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 3f98ec367..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "files.associations": { - "*.icc": "cpp", - "complex": "cpp", - "any": "cpp", - "array": "cpp", - "atomic": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "chrono": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "condition_variable": "cpp", - "csignal": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "list": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "map": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "regex": "cpp", - "set": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "new": "cpp", - "ostream": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "cinttypes": "cpp", - "typeindex": "cpp", - "typeinfo": "cpp", - "valarray": "cpp", - "variant": "cpp" - } -} \ No newline at end of file From 714b0636c495ea033f2f5cacc083ef24b79031eb Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 11 Oct 2023 21:21:13 +0000 Subject: [PATCH 013/106] enable the flatten_path when the azimuth band filter is enabled --- python/packages/nisar/workflows/crossmul.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index daab53618..31cbb491c 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -42,7 +42,7 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', if az_looks == None: az_looks = crossmul_params['azimuth_looks'] - if flatten or do_common_range_band_filter: + if flatten or do_common_range_band_filter or do_common_azimuth_band_filter: flatten_path = crossmul_params['flatten_path'] if output_hdf5 is None: From 5d06c3ef99760827d64b3a805b597462a0276559 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 11 Oct 2023 23:01:51 +0000 Subject: [PATCH 014/106] fix the azimuth filter bugs --- .vscode/settings.json | 5 ++++ cxx/isce3/signal/Crossmul.cpp | 4 +-- cxx/isce3/signal/Filter.cpp | 49 ++++++++++++------------------- cxx/isce3/signal/Filter.h | 7 ++--- tests/cxx/isce3/signal/filter.cpp | 2 +- 5 files changed, 28 insertions(+), 39 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..d7568504d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "complex": "cpp" + } +} \ No newline at end of file diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index c31e790ca..c2458c996 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -443,7 +443,7 @@ crossmul(isce3::io::Raster& refSlcRaster, _refDoppler, _secDoppler, rngOffset, _azimuthBandwidth, _prf, beta, refSlc, refAzimuthSpectrum, fft_size, - linesPerBlock, true, filterType); + linesPerBlock, filterType); azimuthFilter.filter(refSlc, refAzimuthSpectrum); // Construct azimuth common band filter for a block of data of the secondary @@ -451,7 +451,7 @@ crossmul(isce3::io::Raster& refSlcRaster, _refDoppler, _secDoppler, rngOffset, _azimuthBandwidth, _prf, beta, secSlc, secAzimuthSpectrum, fft_size, - linesPerBlock, false, filterType); + linesPerBlock, filterType); azimuthFilter.filter(secSlc, secAzimuthSpectrum); } diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index f4095698b..01f85a9a4 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -256,7 +256,6 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, double beta, std::valarray>& _filter1D) { - // construct a kaiser bandpass filter in frequency domian // which may have several bands defined by centerferquencies and // subBandBandwidths @@ -282,22 +281,22 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, for (size_t ind = indL; ind < fft_size; ++ind){ double fre = fL + (ind - indL) / (dt * fft_size); double tmp = 2.0 * fre * dt; - double kaiserCoefficent = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); - _filter1D[ind] = std::complex(kaiserCoefficent/bessel_i0_beta, 0.0); + double kaiserCoefficient = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); + _filter1D[ind] = std::complex(kaiserCoefficient/bessel_i0_beta, 0.0); } for (size_t ind = 0; ind < indH; ++ind){ double fre = ind / (dt * fft_size); double tmp = 2.0 * fre * dt; - double kaiserCoefficent = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); - _filter1D[ind] = std::complex(kaiserCoefficent/bessel_i0_beta, 0.0); + double kaiserCoefficient = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); + _filter1D[ind] = std::complex(kaiserCoefficient/bessel_i0_beta, 0.0); } }else{ for (size_t ind = indL; ind < indH; ++ind){ double fre = (ind - 0.5 * (indL + indH)) / (dt * fft_size); double tmp = 2.0 * fre * dt; - double kaiserCoefficent = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); - _filter1D[ind] = std::complex(kaiserCoefficent/bessel_i0_beta, 0.0); + double kaiserCoefficient = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); + _filter1D[ind] = std::complex(kaiserCoefficient/bessel_i0_beta, 0.0); } } } @@ -314,7 +313,6 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, * @param[in] spectrum of the block of data * @param[in] ncols number of columns of the block of data * @param[in] nrows number of rows of the block of data -* @param[in] isReferenceSLCFilter filter on the reference SLC, default is true. */ template void @@ -329,7 +327,6 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, std::valarray> &spectrum, size_t ncols, size_t nrows, - bool isReferenceSLCFilter, std::string filterType) { if (filterType=="cosine"){ @@ -339,7 +336,7 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, rangeOffsets, bandwidth, prf, beta, signal, spectrum, - ncols, nrows, isReferenceSLCFilter); + ncols, nrows); } else if (filterType=="kaiser"){ constructAzimuthCommonbandKaiserFilter( @@ -348,7 +345,7 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, rangeOffsets, bandwidth, prf, beta, signal, spectrum, - ncols, nrows, isReferenceSLCFilter); + ncols, nrows); } else{ std::cout << filterType << " filter has not been implemented" << std::endl; } @@ -365,7 +362,6 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, * @param[in] spectrum of the block of data * @param[in] ncols number of columns of the block of data * @param[in] nrows number of rows of the block of data -* @param[in] isReferenceSLCFilter filter on the reference SLC, default is true. */ template void @@ -379,8 +375,7 @@ constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDop std::valarray> &signal, std::valarray> &spectrum, size_t ncols, - size_t nrows, - bool isReferenceSLCFilter) + size_t nrows) { _filter.resize(ncols*nrows); @@ -404,11 +399,8 @@ constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDop // I think we need the range offsets here to restore the fDC // for the secondary doppler since it is the resampled RSLC // middle frequency for the reference SLC - double fmid = -0.5 * (refDoppler.eval(j) - - secDoppler.eval(j + rangeOffsets[j])); - - // for secondary SLC filter - if (!isReferenceSLCFilter) fmid *= -1; + double fmid = 0.5 * (refDoppler.eval(j) + + secDoppler.eval(j + rangeOffsets[j])); // Compute filter for (size_t i = 0; i < frequency.size(); ++i) { @@ -456,7 +448,6 @@ constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDop * @param[in] spectrum of the block of data * @param[in] ncols number of columns of the block of data * @param[in] nrows number of rows of the block of data -* @param[in] isReferenceSLCFilter filter on the reference SLC, default is true. */ template void @@ -470,8 +461,7 @@ constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDop std::valarray> &signal, std::valarray> &spectrum, size_t ncols, - size_t nrows, - bool isReferenceSLCFilter) + size_t nrows) { _filter.resize(ncols*nrows); _filter = std::complex(0.0, 0.0); @@ -483,20 +473,17 @@ constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDop // bessel_i0 of beta double bessel_i0_beta = isce3::math::bessel_i0(beta); - double meanDopFreqshifts = 0.0; + double meanDopCenterFreq = 0.0; // Loop over range bins for (int j = 0; j < ncols; ++j) { // Compute center frequency of common band // I think we need the range offsets here to restore the fDC // for the secondary doppler since it is the resampled RSLC // frequency shift for the reference SLC - double fmid = -0.5 * (refDoppler.eval(j) - + double fmid = 0.5 * (refDoppler.eval(j) + secDoppler.eval(j + rangeOffsets[j])); - // for secondary SLC filter - if (!isReferenceSLCFilter) fmid *= -1; - - meanDopFreqshifts += fmid; + meanDopCenterFreq += fmid; // Compute the filter centered at fmid for (size_t i = 0; i < frequency.size(); ++i) { @@ -508,12 +495,12 @@ constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDop if (freq < -prf/2.0) freq += prf; double tmp = 2.0 * freq / prf; - double kaiserCoefficent = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); - _filter[i*ncols+j] = std::complex(kaiserCoefficent/bessel_i0_beta, 0.0); + double kaiserCoefficient = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); + _filter[i*ncols+j] = std::complex(kaiserCoefficient/bessel_i0_beta, 0.0); } } - std::cout << " - mean doppler centroid shift:" << meanDopFreqshifts/ncols << std::endl; + std::cout << " - mean doppler center freq:" << meanDopCenterFreq/ncols << std::endl; _signal.forwardAzimuthFFT(signal, spectrum, ncols, nrows); _signal.inverseAzimuthFFT(spectrum, signal, ncols, nrows); diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index 3563e9c44..4e298a894 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -99,7 +99,6 @@ class isce3::signal::Filter { std::valarray> &spectrum, size_t ncols, size_t nrows, - bool isReferenceSLCFilter, std::string filterType); /** Construct azimuth common band cosine filter with the doppler centroid compensation*/ @@ -112,8 +111,7 @@ class isce3::signal::Filter { std::valarray> &signal, std::valarray> &spectrum, size_t ncols, - size_t nrows, - bool isReferenceSLCFilter = true); + size_t nrows); /** Construct azimuth common band kaiser filter with the doppler centroid compensation*/ void constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDoppler, @@ -125,8 +123,7 @@ class isce3::signal::Filter { std::valarray> &signal, std::valarray> &spectrum, size_t ncols, - size_t nrows, - bool isReferenceSLCFilter = true); + size_t nrows); /** Filter a signal in frequency domain*/ void filter(std::valarray> &signal, diff --git a/tests/cxx/isce3/signal/filter.cpp b/tests/cxx/isce3/signal/filter.cpp index 44ef688aa..8577bf7ab 100644 --- a/tests/cxx/isce3/signal/filter.cpp +++ b/tests/cxx/isce3/signal/filter.cpp @@ -59,7 +59,7 @@ TEST(Filter, constructAzimuthCommonbandFilter) prf, beta, refSlc, refSpectrum, - ncols, blockRows, true); + ncols, blockRows); filter.writeFilter(ncols, blockRows); } From f81ee9b5d1893d71cf5908ce149121e9a6701695 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 16 Oct 2023 16:30:30 +0000 Subject: [PATCH 015/106] fix range band filter bugs --- cxx/isce3/signal/Crossmul.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index c2458c996..f0b808ea0 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -464,11 +464,14 @@ crossmul(isce3::io::Raster& refSlcRaster, std::cout << " - range pixel spacing: " << _rangePixelSpacing << std::endl; std::cout << " - wavelength: " << _wavelength << std::endl; - // Convert range offset from meters to complex phase + // Convert range offset from meters to complex one-way phase #pragma omp parallel for for (size_t line = 0; line < blockRowsData; ++line) { for (size_t col = 0; col < ncols; ++col) { - double phase = 4.0 * M_PI + + // Use the one-way phase instead of the two-way phase + // to align the spectrum and determin the frequency shifts + double phase = 2.0 * M_PI * _rangePixelSpacing*rngOffset[line*fft_size+col] / _wavelength; From d821dcfd10f16b2a632d8d8fca864d79538c368c Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 23 Oct 2023 16:44:33 +0000 Subject: [PATCH 016/106] fix some issues with the bandpassing --- .vscode/settings.json | 3 +- cxx/isce3/signal/Crossmul.cpp | 17 +- cxx/isce3/signal/Filter.cpp | 2 +- .../isce3/splitspectrum/splitspectrum.py | 232 +++++++++--------- .../packages/nisar/workflows/troposphere.py | 1 - 5 files changed, 125 insertions(+), 130 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index d7568504d..6cd17d3c4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { - "complex": "cpp" + "complex": "cpp", + "*.icc": "cpp" } } \ No newline at end of file diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index f0b808ea0..c8b74d8b1 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -150,14 +150,8 @@ rangeCommonBandFilter(std::valarray> &refSlc, // restore the original phase without the geometry phase // in case other steps will use the original phase - #pragma omp parallel for - for (size_t i = 0; i < vectorLength; ++i) { - double phase = std::arg(geometryIfgram[i]); - refSlc[i] *= - std::complex(std::cos(phase), std::sin(phase)); - secSlc[i] *= std::complex(std::cos(phase), - -1 * std::sin(phase)); - } + refSlc *= geometryIfgram; + secSlc *= geometryIfgramConj; } void isce3::signal::Crossmul:: @@ -437,7 +431,7 @@ crossmul(isce3::io::Raster& refSlcRaster, if (_doCommonAzimuthBandFilter) { std::string filterType = "kaiser"; - double beta = 2.5; + double beta = 1.6; // Construct azimuth common band filter for a block of data of the reference azimuthFilter.constructAzimuthCommonbandFilter( _refDoppler, _secDoppler, rngOffset, @@ -470,7 +464,7 @@ crossmul(isce3::io::Raster& refSlcRaster, for (size_t col = 0; col < ncols; ++col) { // Use the one-way phase instead of the two-way phase - // to align the spectrum and determin the frequency shifts + // to align the spectrum and determine the frequency shifts double phase = 2.0 * M_PI * _rangePixelSpacing*rngOffset[line*fft_size+col] / _wavelength; @@ -536,8 +530,9 @@ crossmul(isce3::io::Raster& refSlcRaster, sum += ifgramUpsampled[line*(ncols*_oversampleFactor) + j + col*_oversampleFactor]; ifgram[line*ncols + col] = sum/ov; - if (_doFlatten) + if (_doFlatten) { ifgram[line*ncols + col] *= geometryIfgramConj[line*fft_size + col]; + } } } diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 01f85a9a4..5b901efcb 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -118,7 +118,7 @@ constructRangeBandpassFilter(double rangeSamplingFrequency, beta, _filter1D); } else if (filterType=="kaiser"){ - double beta = 2.5; + double beta = 1.6; constructRangeBandpassKaiser(subBandCenterFrequencies, subBandBandwidths, dt, diff --git a/python/packages/isce3/splitspectrum/splitspectrum.py b/python/packages/isce3/splitspectrum/splitspectrum.py index 064a0eccc..08cfc34e8 100644 --- a/python/packages/isce3/splitspectrum/splitspectrum.py +++ b/python/packages/isce3/splitspectrum/splitspectrum.py @@ -22,7 +22,7 @@ class bandpass_meta_data: center_freq: float #slant range slant_range: 'method' - + @classmethod def load_from_slc(cls, slc_product, freq): """Get meta data from SLC object. @@ -39,7 +39,7 @@ def load_from_slc(cls, slc_product, freq): """ rdr_grid = slc_product.getRadarGrid(freq) rg_sample_freq = isce3.core.speed_of_light * 0.5 / rdr_grid.range_pixel_spacing - rg_bandwidth = slc_product.getSwathMetadata(freq).processed_range_bandwidth + rg_bandwidth = slc_product.getSwathMetadata(freq).processed_range_bandwidth center_frequency = isce3.core.speed_of_light / rdr_grid.wavelength return cls(rdr_grid.range_pixel_spacing, rdr_grid.wavelength, rg_sample_freq, rg_bandwidth, center_frequency, rdr_grid.slant_range) @@ -48,10 +48,10 @@ def load_from_slc(cls, slc_product, freq): def check_range_bandwidth_overlap(ref_slc, sec_slc, pols): """Check if bandpass is needed. - If the two SLCs differ in center frequency or bandwidth, then - one SLC shall be bandpassed to a common frequency band. If - necessary, determine which SLC will be bandpassed - + If the two SLCs differ in center frequency or bandwidth, then + one SLC shall be bandpassed to a common frequency band. If + necessary, determine which SLC will be bandpassed + Parameters ---------- ref_slc : nisar.products.readers.SLC @@ -63,8 +63,8 @@ def check_range_bandwidth_overlap(ref_slc, sec_slc, pols): Returns ------- - mode : dict - Dict mapping frequency band (e.g. "A" or "B") to + mode : dict + Dict mapping frequency band (e.g. "A" or "B") to SLC to be bandpassed ("ref" or "sec"). """ mode = dict() @@ -72,12 +72,12 @@ def check_range_bandwidth_overlap(ref_slc, sec_slc, pols): for freq, pol_list in pols.items(): ref_meta_data = bandpass_meta_data.load_from_slc(ref_slc, freq) sec_meta_data = bandpass_meta_data.load_from_slc(sec_slc, freq) - + ref_wvl = ref_meta_data.wavelength sec_wvl = sec_meta_data.wavelength ref_bw = ref_meta_data.rg_bandwidth sec_bw = sec_meta_data.rg_bandwidth - + # check if two SLCs have same bandwidth and center frequency if (ref_wvl != sec_wvl) or (ref_bw != sec_bw): if ref_bw > sec_bw: @@ -89,29 +89,29 @@ def check_range_bandwidth_overlap(ref_slc, sec_slc, pols): class SplitSpectrum: ''' - Split the slant range spectrum + Split the slant range spectrum ''' - def __init__(self, - rg_sample_freq, - rg_bandwidth, - center_frequency, - slant_range, + def __init__(self, + rg_sample_freq, + rg_bandwidth, + center_frequency, + slant_range, freq): """Initialized Bandpass Class with SLC meta data - + Parameters ---------- rg_sample_freq : float - range sampling frequency + range sampling frequency rg_bandwidth : float range bandwidth [Hz] - center_frequency : float + center_frequency : float center frequency of SLC [Hz] slant_range : new center frequency for bandpass [Hz] freq : {'A', 'B'} frequency band - """ + """ self.freq = freq self.rg_sample_freq = rg_sample_freq self.rg_pxl_spacing = isce3.core.speed_of_light / 2.0 / self.rg_sample_freq @@ -120,24 +120,24 @@ def __init__(self, self.slant_range = slant_range def bandpass_shift_spectrum(self, - slc_raster, - low_frequency, + slc_raster, + low_frequency, high_frequency, new_center_frequency, window_function, - window_shape=0.25, - fft_size=None, + window_shape=0.25, + fft_size=None, resampling=True ): - """Bandpass SLC for a given bandwidth and shift the bandpassed + """Bandpass SLC for a given bandwidth and shift the bandpassed spectrum to a new center frequency - + Parameters ---------- - slc_raster : numpy.ndarray - numpy array of slc raster, - low_frequency : float + slc_raster : numpy.ndarray + numpy array of slc raster, + low_frequency : float low frequency of band to be passed [Hz] high_frequency : float high frequency band to be passed [Hz] @@ -145,24 +145,24 @@ def bandpass_shift_spectrum(self, new center frequency for new bandpassed slc [Hz] window_function : str window type {tukey, kaiser, cosine} - window_shape : float + window_shape : float parameter for the raised cosine filter (e.g. 0 ~ 1) - fft_size : int - fft size. + fft_size : int + fft size. resampling : bool if True, then resample SLC and meta data with new range spacing If False, return SLC and meta with original range spacing Returns ------- - resampled_slc or slc_demodulate: numpy.ndarray + resampled_slc or slc_demodulate: numpy.ndarray numpy array of bandpassed slc - if resampling is True, return resampled slc with bandpass and demodulation + if resampling is True, return resampled slc with bandpass and demodulation if resampling is False, return slc with bandpass and demodulation without resampling - meta : dict + meta : dict dict containing meta data of bandpassed slc center_frequency, rg_bandwidth, range_spacing, slant_range - """ + """ error_channel = journal.error('splitspectrum.bandpass_shift_spectrum') rg_sample_freq = self.rg_sample_freq @@ -171,22 +171,22 @@ def bandpass_shift_spectrum(self, height, width = slc_raster.shape slc_raster = np.asanyarray(slc_raster, dtype='complex') - slc_bp = self.bandpass_spectrum( - slc_raster=slc_raster, - low_frequency=low_frequency, + slc_bp = self.bandpass_spectrum( + slc_raster=slc_raster, + low_frequency=low_frequency, high_frequency=high_frequency, window_function=window_function, - window_shape=window_shape, - fft_size=fft_size, + window_shape=window_shape, + fft_size=fft_size, ) # demodulate the SLC to be baseband to new center frequency # if fft_size > width, then crop the spectrum from 0 to width - slc_demodulate = self.demodulate_slc(slc_bp[:, :width], - diff_frequency, + slc_demodulate = self.demodulate_slc(slc_bp[:, :width], + diff_frequency, rg_sample_freq) - # update metadata with new parameters + # update metadata with new parameters meta = dict() new_bandwidth = high_frequency - low_frequency meta['center_frequency'] = new_center_frequency @@ -201,9 +201,9 @@ def bandpass_shift_spectrum(self, # find the maximum of the multiple of resampling_scale_factor resample_width_end = np.max(x_cand[x_cand % resampling_scale_factor == 0]) - # resample SLC + # resample SLC resampled_slc = resample(slc_demodulate[:, :resample_width_end], sub_width, axis=1) - + meta['range_spacing'] = self.rg_pxl_spacing * resampling_scale_factor meta['slant_range'] = np.linspace(self.slant_range(0), self.slant_range(width), sub_width, endpoint=False) @@ -211,44 +211,44 @@ def bandpass_shift_spectrum(self, return resampled_slc, meta else: - meta['range_spacing'] = self.rg_pxl_spacing + meta['range_spacing'] = self.rg_pxl_spacing meta['slant_range'] = np.linspace(self.slant_range(0), self.slant_range(width), width, endpoint=False) return slc_demodulate, meta - - def bandpass_spectrum(self, - slc_raster, - low_frequency, + + def bandpass_spectrum(self, + slc_raster, + low_frequency, high_frequency, window_function, - window_shape=0.25, - fft_size=None, + window_shape=0.25, + fft_size=None, ): """Bandpass SLC for given center frequency and bandwidth - + Parameters ---------- - slc_raster : numpy.ndarray - numpy array of slc raster, - low_frequency : float + slc_raster : numpy.ndarray + numpy array of slc raster, + low_frequency : float low frequency of band to be passed [Hz] high_frequency : float high frequency band to be passed [Hz] window_function: str window type {'tukey', 'kaiser', 'cosine'} - window_shape : float + window_shape : float parameter for the window shape kaiser 0<= window_shape < inf tukey and cosine 0 <= window_shape <= 1 - fft_size : int - fft size. + fft_size : int + fft size. Returns ------- - slc_bandpassed : numpy.ndarray + slc_bandpassed : numpy.ndarray numpy array of bandpassed slc - """ + """ error_channel = journal.error('splitspectrum.bandpass_spectrum') rg_sample_freq = self.rg_sample_freq @@ -266,7 +266,7 @@ def bandpass_spectrum(self, if fft_size is None: fft_size = width - + if fft_size < width: err_str = f"FFT size is smaller than number of range bins" error_channel.log(err_str) @@ -277,56 +277,56 @@ def bandpass_spectrum(self, center_frequency=0, freq_low=-rg_bandwidth/2, freq_high=rg_bandwidth/2, - sampling_frequency=rg_sample_freq, + sampling_frequency=rg_sample_freq, fft_size=fft_size, window_function=window_function, window_shape=window_shape ) - # construct window to bandpass spectrum + # construct window to bandpass spectrum # for given low and high frequencies window_bandpass = self.get_range_bandpass_window( center_frequency=0, freq_low=low_frequency - center_frequency, freq_high=high_frequency - center_frequency, - sampling_frequency=rg_sample_freq, + sampling_frequency=rg_sample_freq, fft_size=fft_size, window_function=window_function, window_shape=window_shape ) - # remove the windowing effect from the spectrum + # remove the windowing effect from the spectrum spectrum_target = fft(slc_raster, n=fft_size, workers=-1) spectrum_target = np.divide(spectrum_target, window_target, out=np.zeros_like(spectrum_target), where=window_target!=0) - # apply new bandpass window to spectrum - slc_bandpassed = ifft(spectrum_target + # apply new bandpass window to spectrum + slc_bandpassed = ifft(spectrum_target * window_bandpass - * np.sqrt(resampling_scale_factor), - n=fft_size, + * np.sqrt(resampling_scale_factor), + n=fft_size, workers=-1) return slc_bandpassed def demodulate_slc(self, slc_array, diff_frequency, rg_sample_freq): - """ Demodulate SLC - - If diff_frequency is not zero, then the spectrum of SLC is shifted + """ Demodulate SLC + + If diff_frequency is not zero, then the spectrum of SLC is shifted so that the sub-band slc is demodulated to center the sub band spectrum Parameters ---------- - slc_array : numpy.ndarray + slc_array : numpy.ndarray SLC raster or block of SLC raster - diff_frequency : float - difference between original and new center frequency [Hz] - rg_sample_freq : float + diff_frequency : float + difference between original and new center frequency [Hz] + rg_sample_freq : float range sampling frequency [Hz] Returns ------- - slc_baseband : numpy.ndarray + slc_baseband : numpy.ndarray demodulated SLC """ height, width = slc_array.shape @@ -337,12 +337,12 @@ def demodulate_slc(self, slc_array, diff_frequency, rg_sample_freq): def freq_spectrum(self, cfrequency, dt, fft_size): ''' Return Discrete Fourier Transform sample frequencies with center frequency bias. - + Parameters: ---------- cfrequency : float Center frequency (Hz) - dt : float + dt : float Sample spacing. fft_size : int Window length. @@ -354,7 +354,7 @@ def freq_spectrum(self, cfrequency, dt, fft_size): freq = cfrequency + fftfreq(fft_size, dt) return freq - def get_range_bandpass_window(self, + def get_range_bandpass_window(self, center_frequency, sampling_frequency, fft_size, @@ -363,14 +363,14 @@ def get_range_bandpass_window(self, window_function='tukey', window_shape=0.25): '''Get range bandpass window such as Tukey, Kaiser, cosine. - Window is constructed in frequency domain from low to high frequencies - with given window_function and shape. + Window is constructed in frequency domain from low to high frequencies + with given window_function and shape. Parameters ---------- center_frequency : float Center frequency of frequency bin [Hz] - If slc is basebanded, center_frequency can be 0. + If slc is basebanded, center_frequency can be 0. sampling_frequency : float sampling frequency [Hz] fft_size : int @@ -381,7 +381,7 @@ def get_range_bandpass_window(self, high frequency to be passed [Hz] window_function : str window type {tukey, kaiser, cosine} - window_shape : float + window_shape : float parameter for the window shape kaiser 0<= window_shape < inf tukey and cosine 0 <= window_shape <= 1 @@ -392,13 +392,13 @@ def get_range_bandpass_window(self, one dimensional bandpass filter in frequency domain ''' error_channel = journal.error('splitspectrum.get_range_bandpass_window') - # construct the frequency bin [Hz] + # construct the frequency bin [Hz] frequency = self.freq_spectrum( cfrequency=center_frequency, dt=1.0/sampling_frequency, fft_size=fft_size - ) - + ) + window_kind = window_function.lower() # Windowing effect will appear from freq_low to freq_high for given frequency bin @@ -407,27 +407,27 @@ def get_range_bandpass_window(self, err_str = f"Expected window_shape between 0 and 1, got {window_shape}." error_channel.log(err_str) raise ValueError(err_str) - + filter_1d = self.construct_range_bandpass_tukey( frequency_range=frequency, freq_low=freq_low, freq_high=freq_high, window_shape=window_shape ) - + elif window_kind == 'kaiser': if not (window_shape > 0): err_str = f"Expected pedestal bigger than 0, got {window_shape}." error_channel.log(err_str) raise ValueError(err_str) - + filter_1d = self.construct_range_bandpass_kaiser( frequency_range=frequency, freq_low=freq_low, freq_high=freq_high, window_shape=window_shape ) - + elif window_kind == 'cosine': if not (0 <= window_shape <= 1): err_str = f"Expected window_shape between 0 and 1, got {window_shape}." @@ -438,16 +438,16 @@ def get_range_bandpass_window(self, freq_low=freq_low, freq_high=freq_high, window_shape=window_shape - ) - + ) + else: err_str = f"window {window_kind} not in (Kaiser, Cosine, Tukey)." error_channel.log(err_str) raise ValueError(err_str) - + return filter_1d - def construct_range_bandpass_cosine(self, + def construct_range_bandpass_cosine(self, frequency_range, freq_low, freq_high, @@ -462,14 +462,14 @@ def construct_range_bandpass_cosine(self, low frequency to be passed [Hz] freq_high: float high frequency to be passed [Hz] - window_shape : float + window_shape : float parameter for the cosine window Returns ------- filter_1d : np.ndarray one dimensional Cosine bandpass filter in frequency domain - ''' + ''' filter_1d = self._construct_range_bandpass_kaiser_cosine(frequency_range, freq_low, freq_high, @@ -477,7 +477,7 @@ def construct_range_bandpass_cosine(self, window_shape) return filter_1d - def construct_range_bandpass_kaiser(self, + def construct_range_bandpass_kaiser(self, frequency_range, freq_low, freq_high, @@ -492,7 +492,7 @@ def construct_range_bandpass_kaiser(self, low frequency to be passed [Hz] freq_high: float high frequency to be passed [Hz] - window_shape : float + window_shape : float parameter for the kaiser window Returns @@ -507,7 +507,7 @@ def construct_range_bandpass_kaiser(self, window_shape) return filter_1d - def _construct_range_bandpass_kaiser_cosine(self, + def _construct_range_bandpass_kaiser_cosine(self, frequency_range, freq_low, freq_high, @@ -523,9 +523,9 @@ def _construct_range_bandpass_kaiser_cosine(self, low frequency to be passed [Hz] freq_high: float high frequency to be passed [Hz] - window_function : class function + window_function : class function window type {np.kaiser, cosine_window} - window_shape : float + window_shape : float parameter for the kaiser window Returns @@ -536,16 +536,16 @@ def _construct_range_bandpass_kaiser_cosine(self, subbandwidth = np.abs(freq_high - freq_low) fft_size = len(frequency_range) - + if freq_high > np.max(frequency_range): err_str = f"High frequency is out of frequency bins." error_channel.log(err_str) raise ValueError(err_str) - + if freq_low < np.min(frequency_range): err_str = f"Low frequency is out of frequency bins." error_channel.log(err_str) - raise ValueError(err_str) + raise ValueError(err_str) # sampling frequency is 1.2 times wider than bandwith sampling_bandwidth_ratio = 1.2 @@ -555,18 +555,18 @@ def _construct_range_bandpass_kaiser_cosine(self, # index for low and high sampling frequency in frequency_range idx_freq_low = np.abs(frequency_range - sampling_low_frequency).argmin() idx_freq_high = np.abs(frequency_range - sampling_high_frequency).argmin() - - if idx_freq_low >= idx_freq_high: + + if idx_freq_low >= idx_freq_high: subband_length = idx_freq_high + fft_size - idx_freq_low + 1 else: subband_length = idx_freq_high - idx_freq_low + 1 - + filter_1d = np.zeros([fft_size], dtype='complex') - # window_function is function class {np.kaiser or consine} + # window_function is function class {np.kaiser or consine} subwindow = window_function(subband_length, window_shape) - if idx_freq_low >= idx_freq_high: + if idx_freq_low >= idx_freq_high: filter_1d[idx_freq_low :] = subwindow[0 : fft_size - idx_freq_low] filter_1d[: idx_freq_high + 1] = subwindow[fft_size - idx_freq_low:] else: @@ -585,11 +585,11 @@ def construct_range_bandpass_tukey(self, ---------- frequency_range : np.ndarray Discrete Fourier Transform sample frequency range [Hz] - freq_low : float + freq_low : float low frequency to be passed [Hz] - freq_high, : list of float + freq_high, : list of float high frequency to be passed [Hz] - window_shape : float + window_shape : float parameter for the Tukey (raised cosine) filter Returns @@ -614,6 +614,6 @@ def construct_range_bandpass_tukey(self, # Transition region elif ((freq < freq_low + df) and (freq >= freq_low - df)) \ or ((freq <= freq_high + df) and (freq > freq_high - df)): - filter_1d[i] = 0.5 * (1.0 + np.cos(np.pi / (subbandwidth * window_shape) + filter_1d[i] = 0.5 * (1.0 + np.cos(np.pi / (subbandwidth * window_shape) * (freqabs - 0.5 * (1.0 - window_shape) * subbandwidth))) return filter_1d \ No newline at end of file diff --git a/python/packages/nisar/workflows/troposphere.py b/python/packages/nisar/workflows/troposphere.py index a1ee3b27e..d438f6d36 100644 --- a/python/packages/nisar/workflows/troposphere.py +++ b/python/packages/nisar/workflows/troposphere.py @@ -158,7 +158,6 @@ def _convert_HRES_to_raider_NetCDF(weather_model_file, weather_model_output_dir): ''' Internal convenience function to convert the ECMWF NetCDF to RAiDER NetCDF - Parameters ---------- weather_model_file: str From 7169c5df6392493fbc5b789e3d80504a0b50a7ef Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 24 Oct 2023 02:39:08 +0000 Subject: [PATCH 017/106] fix the azimuth filter --- .vscode/settings.json | 65 ++++++++++++++++++++++++++++++++++- cxx/isce3/signal/Crossmul.cpp | 4 +-- cxx/isce3/signal/Filter.cpp | 26 +++++++++----- 3 files changed, 84 insertions(+), 11 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 6cd17d3c4..a51a3b835 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,69 @@ { "files.associations": { "complex": "cpp", - "*.icc": "cpp" + "*.icc": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "condition_variable": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "set": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "valarray": "cpp", + "variant": "cpp" } } \ No newline at end of file diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index c8b74d8b1..a0d26f674 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -122,7 +122,7 @@ rangeCommonBandFilter(std::valarray> &refSlc, std::valarray filterCenterFrequency{0.0}; std::valarray filterBandwidth{_rangeBandwidth - fabs(frequencyShift)}; - std::string filterType = "cosine"; + std::string filterType = "kaiser"; // Contruct the low pass filter for this block. This filter is // common for both SLCs @@ -431,7 +431,7 @@ crossmul(isce3::io::Raster& refSlcRaster, if (_doCommonAzimuthBandFilter) { std::string filterType = "kaiser"; - double beta = 1.6; + double beta = 2.5; // Construct azimuth common band filter for a block of data of the reference azimuthFilter.constructAzimuthCommonbandFilter( _refDoppler, _secDoppler, rngOffset, diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 5b901efcb..2045913db 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -474,15 +474,19 @@ constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDop // bessel_i0 of beta double bessel_i0_beta = isce3::math::bessel_i0(beta); double meanDopCenterFreq = 0.0; + double meanDopCenterFreqShift = 0.0; // Loop over range bins for (int j = 0; j < ncols; ++j) { // Compute center frequency of common band - // I think we need the range offsets here to restore the fDC - // for the secondary doppler since it is the resampled RSLC - // frequency shift for the reference SLC - double fmid = 0.5 * (refDoppler.eval(j) + - secDoppler.eval(j + rangeOffsets[j])); + // the range offsets here are to restore the fDC + // for the secondary doppler since it has been resampled + double refFreq = refDoppler.eval(j); + double secFreq = secDoppler.eval(j + rangeOffsets[j]); + + double fmid = 0.5 * (refFreq + secFreq); + double fshift = std::abs(refFreq - secFreq); + meanDopCenterFreqShift += fshift; meanDopCenterFreq += fmid; // Compute the filter centered at fmid @@ -494,13 +498,19 @@ constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDop if (freq > prf/2.0) freq -= prf; if (freq < -prf/2.0) freq += prf; - double tmp = 2.0 * freq / prf; - double kaiserCoefficient = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); - _filter[i*ncols+j] = std::complex(kaiserCoefficient/bessel_i0_beta, 0.0); + if (std::abs(freq) > 0.5 * (bandwidth - fshift)) { + _filter[i*ncols+j] = std::complex(0.0,0.0); + } + else { + double tmp = 2.0 * freq / prf; + double kaiserCoefficient = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); + _filter[i*ncols+j] = std::complex(kaiserCoefficient/bessel_i0_beta, 0.0); + } } } std::cout << " - mean doppler center freq:" << meanDopCenterFreq/ncols << std::endl; + std::cout << " - mean doppler center freq shift:" << meanDopCenterFreqShift/ncols << std::endl; _signal.forwardAzimuthFFT(signal, spectrum, ncols, nrows); _signal.inverseAzimuthFFT(spectrum, signal, ncols, nrows); From b90dfe1be46a0c2e29579039feac4566310bf52a Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 24 Oct 2023 04:37:29 +0000 Subject: [PATCH 018/106] remove vscode files --- .vscode/settings.json | 69 ------------------------------------------- 1 file changed, 69 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index a51a3b835..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "files.associations": { - "complex": "cpp", - "*.icc": "cpp", - "any": "cpp", - "array": "cpp", - "atomic": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "chrono": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "condition_variable": "cpp", - "csignal": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "list": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "map": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "regex": "cpp", - "set": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "new": "cpp", - "ostream": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "cinttypes": "cpp", - "typeindex": "cpp", - "typeinfo": "cpp", - "valarray": "cpp", - "variant": "cpp" - } -} \ No newline at end of file From 25db581fe60ae03023dba460c1284c78df114e9a Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 30 Oct 2023 17:57:56 +0000 Subject: [PATCH 019/106] fix the segmentation fault of range filter --- cxx/isce3/signal/Crossmul.cpp | 5 ++--- cxx/isce3/signal/Filter.cpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index a0d26f674..67fd462e0 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -147,7 +147,6 @@ rangeCommonBandFilter(std::valarray> &refSlc, blockLength, filterType); rngFilter.filter(secSlc, secSpectrum); - // restore the original phase without the geometry phase // in case other steps will use the original phase refSlc *= geometryIfgram; @@ -431,7 +430,7 @@ crossmul(isce3::io::Raster& refSlcRaster, if (_doCommonAzimuthBandFilter) { std::string filterType = "kaiser"; - double beta = 2.5; + double beta = 1.6; // Construct azimuth common band filter for a block of data of the reference azimuthFilter.constructAzimuthCommonbandFilter( _refDoppler, _secDoppler, rngOffset, @@ -485,7 +484,7 @@ crossmul(isce3::io::Raster& refSlcRaster, // and the resultant refSlc and secSlc have no topo phase removal rangeCommonBandFilter(refSlc, secSlc, geometryIfgram, geometryIfgramConj, refSpectrum, secSpectrum, - rangeFrequencies, rangeFilter, blockRowsData, fft_size); + rangeFrequencies, rangeFilter, linesPerBlock, fft_size); } // upsample the reference and secondary SLCs diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 2045913db..7a7dac39a 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -272,7 +272,7 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, indexOfFrequency(dt, fft_size, fL, indL); int indH; indexOfFrequency(dt, fft_size, fH, indH); - std::cout << "fL: "<< fL << " , fH: " << fH << " indL: " << indL << " , indH: " << indH << std::endl; + std::cout << " - fL: "<< fL << " , fH: " << fH << " indL: " << indL << " , indH: " << indH << std::endl; // bessel_i0 of beta double bessel_i0_beta = isce3::math::bessel_i0(beta); From 0cddc63c8b06a965830a6473d2a387bda6b2475d Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 30 Oct 2023 19:24:53 +0000 Subject: [PATCH 020/106] populate the azimuth and range bandwidth --- cxx/isce3/signal/Crossmul.cpp | 40 ++++++++++++++----- cxx/isce3/signal/Crossmul.h | 34 +++++++++++----- cxx/isce3/signal/Filter.cpp | 37 ++++++++++++----- cxx/isce3/signal/Filter.h | 6 +-- .../pybind_isce3/signal/Crossmul.cpp | 2 + python/packages/nisar/workflows/crossmul.py | 17 +++++++- 6 files changed, 103 insertions(+), 33 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 67fd462e0..7c4423ce5 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -78,7 +78,7 @@ size_t omp_thread_count() { * @param[in] blockLength number of rows * @param[in] ncols number of columns */ -void isce3::signal::Crossmul:: +double isce3::signal::Crossmul:: rangeCommonBandFilter(std::valarray> &refSlc, std::valarray> &secSlc, std::valarray> geometryIfgram, @@ -151,6 +151,8 @@ rangeCommonBandFilter(std::valarray> &refSlc, // in case other steps will use the original phase refSlc *= geometryIfgram; secSlc *= geometryIfgramConj; + + return (_rangeBandwidth - frequencyShift); } void isce3::signal::Crossmul:: @@ -246,6 +248,18 @@ crossmul(isce3::io::Raster& refSlcRaster, nblocks += 1; } + // set up the processed azimuth and range bandwidth + if (_doCommonAzimuthBandFilter) { + _processedAzimuthBandwidth = 0.0; + } else { + _processedAzimuthBandwidth = _azimuthBandwidth; + } + if (_doCommonRangeBandFilter) { + _processedRangeBandwidth = 0.0; + } else { + _processedRangeBandwidth = _rangeBandwidth; + } + // size of not-unsampled valarray const auto spectrumSize = fft_size * linesPerBlock; @@ -427,16 +441,18 @@ crossmul(isce3::io::Raster& refSlcRaster, } //common azimuth band-pass filter the reference and secondary SLCs + //TODO: since there is no windowing is applied in azimuth, no need to revert + //the windowing effects, and the attena pattern coefficents are not stored in the + //SLC yet, will wait for the implementation and revert the attena pattern then if (_doCommonAzimuthBandFilter) { - std::string filterType = "kaiser"; double beta = 1.6; // Construct azimuth common band filter for a block of data of the reference - azimuthFilter.constructAzimuthCommonbandFilter( - _refDoppler, _secDoppler, rngOffset, - _azimuthBandwidth, - _prf, beta, refSlc, refAzimuthSpectrum, fft_size, - linesPerBlock, filterType); + _processedAzimuthBandwidth += azimuthFilter.constructAzimuthCommonbandFilter( + _refDoppler, _secDoppler, rngOffset, + _azimuthBandwidth, + _prf, beta, refSlc, refAzimuthSpectrum, fft_size, + linesPerBlock, filterType); azimuthFilter.filter(refSlc, refAzimuthSpectrum); // Construct azimuth common band filter for a block of data of the secondary @@ -482,9 +498,9 @@ crossmul(isce3::io::Raster& refSlcRaster, // Apply range common band filter to ref and sec SLC // and the resultant refSlc and secSlc have no topo phase removal - rangeCommonBandFilter(refSlc, secSlc, geometryIfgram, - geometryIfgramConj, refSpectrum, secSpectrum, - rangeFrequencies, rangeFilter, linesPerBlock, fft_size); + _processedRangeBandwidth += rangeCommonBandFilter(refSlc, secSlc, geometryIfgram, + geometryIfgramConj, refSpectrum, secSpectrum, + rangeFrequencies, rangeFilter, linesPerBlock, fft_size); } // upsample the reference and secondary SLCs @@ -581,4 +597,8 @@ crossmul(isce3::io::Raster& refSlcRaster, blockRowsData); } } + + // update the azimuth and range bandwidth after common band filtering + if (_doCommonRangeBandFilter) _processedRangeBandwidth /= nblocks; + if (_doCommonAzimuthBandFilter) _processedAzimuthBandwidth /= nblocks; } diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 4d2afe2dd..89dbe27d7 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -89,6 +89,10 @@ class isce3::signal::Crossmul { inline double azimuthBandwidth() const { return _azimuthBandwidth; } + /** Get processed azimuth bandwidth */ + inline double processedAzimuthBandwidth() const { + return _processedAzimuthBandwidth; } + /** Set beta parameter for the azimuth common band filter */ inline void beta(double beta) { _beta = beta; } @@ -129,6 +133,10 @@ class isce3::signal::Crossmul { /** Get the range bandwidth */ inline double rangeBandwidth() const {return _rangeBandwidth; } + /** Get processed range bandwidth after common band filter*/ + inline double processedRangeBandwidth() const { + return _processedRangeBandwidth; } + /** Set oversample factor */ inline void oversampleFactor(size_t oversamp) { _oversampleFactor = oversamp; } @@ -157,16 +165,16 @@ class isce3::signal::Crossmul { size_t &peakIndex); /** Range common band filtering*/ - void rangeCommonBandFilter(std::valarray> &refSlc, - std::valarray> &secSlc, - std::valarray> geometryIfgram, - std::valarray> geometryIfgramConj, - std::valarray> &refSpectrum, - std::valarray> &secSpectrum, - std::valarray &rangeFrequencies, - isce3::signal::Filter &rngFilter, - size_t blockRows, - size_t ncols); + double rangeCommonBandFilter(std::valarray> &refSlc, + std::valarray> &secSlc, + std::valarray> geometryIfgram, + std::valarray> geometryIfgramConj, + std::valarray> &refSpectrum, + std::valarray> &secSpectrum, + std::valarray &rangeFrequencies, + isce3::signal::Filter &rngFilter, + size_t blockRows, + size_t ncols); private: //Doppler LUT for the refernce SLC @@ -198,6 +206,9 @@ class isce3::signal::Crossmul { // Azimuth bandwidth double _azimuthBandwidth; + // Processed azimuth bandwidth after the common band filtering + double _processedAzimuthBandwidth; + // Beta parameter for constructing common azimuth band filter double _beta = 0.25; @@ -213,6 +224,9 @@ class isce3::signal::Crossmul { // range signal bandwidth double _rangeBandwidth; + // Processed range bandwidth after the common band filtering + double _processedRangeBandwidth; + // number of lines per block size_t _linesPerBlock = 1024; diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 7a7dac39a..6bfb67a8d 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -315,7 +315,7 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, * @param[in] nrows number of rows of the block of data */ template -void +double isce3::signal::Filter:: constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, const isce3::core::LUT1d & secDoppler, @@ -330,7 +330,7 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, std::string filterType) { if (filterType=="cosine"){ - constructAzimuthCommonbandCosineFilter( + return constructAzimuthCommonbandCosineFilter( refDoppler, secDoppler, rangeOffsets, @@ -339,7 +339,7 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, ncols, nrows); } else if (filterType=="kaiser"){ - constructAzimuthCommonbandKaiserFilter( + return constructAzimuthCommonbandKaiserFilter( refDoppler, secDoppler, rangeOffsets, @@ -348,6 +348,7 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, ncols, nrows); } else{ std::cout << filterType << " filter has not been implemented" << std::endl; + return bandwidth; } } @@ -364,7 +365,7 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, * @param[in] nrows number of rows of the block of data */ template -void +double isce3::signal::Filter:: constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDoppler, const isce3::core::LUT1d & secDoppler, @@ -393,15 +394,22 @@ constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDop std::valarray frequency(fft_size); fftfreq(1.0/prf, frequency); + double meanDopCenterFreq = 0.0; + double meanDopCenterFreqShift = 0.0; // Loop over range bins for (int j = 0; j < ncols; ++j) { // Compute center frequency of common band // I think we need the range offsets here to restore the fDC // for the secondary doppler since it is the resampled RSLC // middle frequency for the reference SLC - double fmid = 0.5 * (refDoppler.eval(j) + - secDoppler.eval(j + rangeOffsets[j])); + double refFreq = refDoppler.eval(j); + double secFreq = secDoppler.eval(j + rangeOffsets[j]); + double fmid = 0.5 * (refFreq + secFreq); + double fshift = std::abs(refFreq - secFreq); + + meanDopCenterFreqShift += fshift; + meanDopCenterFreq += fmid; // Compute filter for (size_t i = 0; i < frequency.size(); ++i) { @@ -433,8 +441,15 @@ constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDop } } + meanDopCenterFreq /= ncols; + meanDopCenterFreqShift /= ncols; + std::cout << " - mean doppler center freq:" << meanDopCenterFreq << std::endl; + std::cout << " - mean doppler center freq shift:" << meanDopCenterFreqShift << std::endl; + _signal.forwardAzimuthFFT(signal, spectrum, ncols, nrows); _signal.inverseAzimuthFFT(spectrum, signal, ncols, nrows); + + return (bandwidth - meanDopCenterFreqShift); } /** @@ -450,7 +465,7 @@ constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDop * @param[in] nrows number of rows of the block of data */ template -void +double isce3::signal::Filter:: constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDoppler, const isce3::core::LUT1d & secDoppler, @@ -509,11 +524,15 @@ constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDop } } - std::cout << " - mean doppler center freq:" << meanDopCenterFreq/ncols << std::endl; - std::cout << " - mean doppler center freq shift:" << meanDopCenterFreqShift/ncols << std::endl; + meanDopCenterFreq /= ncols; + meanDopCenterFreqShift /= ncols; + std::cout << " - mean doppler center freq:" << meanDopCenterFreq << std::endl; + std::cout << " - mean doppler center freq shift:" << meanDopCenterFreqShift << std::endl; _signal.forwardAzimuthFFT(signal, spectrum, ncols, nrows); _signal.inverseAzimuthFFT(spectrum, signal, ncols, nrows); + + return (bandwidth - meanDopCenterFreqShift); } diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index 4e298a894..dac4157b5 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -89,7 +89,7 @@ class isce3::signal::Filter { std::valarray>& _filter1D); /** Construct azimuth common band filter*/ - void constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, + double constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, const isce3::core::LUT1d & secDoppler, std::valarray &rangeOffsets, double bandwidth, @@ -102,7 +102,7 @@ class isce3::signal::Filter { std::string filterType); /** Construct azimuth common band cosine filter with the doppler centroid compensation*/ - void constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDoppler, + double constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDoppler, const isce3::core::LUT1d & secDoppler, std::valarray &rangeOffsets, double bandwidth, @@ -114,7 +114,7 @@ class isce3::signal::Filter { size_t nrows); /** Construct azimuth common band kaiser filter with the doppler centroid compensation*/ - void constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDoppler, + double constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDoppler, const isce3::core::LUT1d & secDoppler, std::valarray &rangeOffsets, double bandwidth, diff --git a/python/extensions/pybind_isce3/signal/Crossmul.cpp b/python/extensions/pybind_isce3/signal/Crossmul.cpp index c674af365..d0912091e 100644 --- a/python/extensions/pybind_isce3/signal/Crossmul.cpp +++ b/python/extensions/pybind_isce3/signal/Crossmul.cpp @@ -95,5 +95,7 @@ void addbinding(py::class_ & pyCrossmul) py::overload_cast<>(&Crossmul::linesPerBlock, py::const_), py::overload_cast(&Crossmul::linesPerBlock)) .def_property_readonly("multilook_enabled", &Crossmul::multiLookEnabled) + .def_property_readonly("processed_range_bandwidth", &Crossmul::processedRangeBandwidth) + .def_property_readonly("processed_azimuth_bandwidth", &Crossmul::processedAzimuthBandwidth) ; } diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index d78936bdf..d485f0ce2 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -14,6 +14,8 @@ gdal.UseExceptions() from nisar.products.readers import SLC +from nisar.products.insar import product_paths + from nisar.workflows import prepare_insar_hdf5 from nisar.workflows.compute_stats import compute_stats_real_data from nisar.workflows.crossmul_runconfig import CrossmulRunConfig @@ -103,7 +105,7 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', sec_slc.getDopplerCentroid(frequency=freq)) crossmul.set_dopplers(ref_dopp, sec_dopp) - freq_group_path = f'/science/LSAR/RIFG/swaths/frequency{freq}' + freq_group_path = f'{product_paths.RIFGGroupsPaths().SwathsPath}/frequency{freq}' # prepare flattening and range filter parameters rdr_grid = ref_slc.getRadarGrid(freq) @@ -188,6 +190,19 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', crossmul.crossmul(ref_slc_raster, sec_slc_raster, ifg_raster, coh_raster, flatten_raster) + # populate the new bandwidth along azimuth and range + # TODO: GPU + if not use_gpu: + processing_info_path = \ + product_paths.RIFGGroupsPaths().ProcessingInformationPath + ifgram_processing_parameter = \ + f'{processing_info_path}/parameters/interferogram/frequency{freq}' + # Update the bandwidth + dst_h5[f'{ifgram_processing_parameter}/azimuthBandwidth'][...] = \ + crossmul.processed_azimuth_bandwidth + dst_h5[f'{ifgram_processing_parameter}/rangeBandwidth'][...] = \ + crossmul.processed_range_bandwidth + del ifg_raster # Allocate raster statistics for coherence From f92765aebd235f5c22cf55747e3278743caadb46 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 30 Oct 2023 19:27:12 +0000 Subject: [PATCH 021/106] docstring --- python/packages/nisar/workflows/crossmul.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index d485f0ce2..127c1290a 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -190,7 +190,9 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', crossmul.crossmul(ref_slc_raster, sec_slc_raster, ifg_raster, coh_raster, flatten_raster) - # populate the new bandwidth along azimuth and range + # populate the new bandwidth along azimuth and range after the common band filter + # if there is no common band filter applied, the bandwith will remain the same with + # the orignal SLC bandwith # TODO: GPU if not use_gpu: processing_info_path = \ From 09c60f8fc55b774c33f47b9cfda985fdc3614cd4 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 30 Oct 2023 21:07:27 +0000 Subject: [PATCH 022/106] revert the range kaiser windowing --- .vscode/settings.json | 69 ++++++++++++++++++++++++++ cxx/isce3/signal/Crossmul.cpp | 92 +++++++++++++++++++++++++---------- 2 files changed, 135 insertions(+), 26 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..9403e2971 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,69 @@ +{ + "files.associations": { + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "set": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "valarray": "cpp", + "variant": "cpp", + "*.icc": "cpp" + } +} \ No newline at end of file diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 7c4423ce5..047ad80af 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -219,6 +219,12 @@ crossmul(isce3::io::Raster& refSlcRaster, //signal object for geometryIfgramConj isce3::signal::Signal geometryIfgramConjSignal(nthreads); + //signal object for refSlc windowing effects revert + isce3::signal::Signal refWindowSignal(nthreads); + + //signal object for secSlc windowing effects revert + isce3::signal::Signal secWindowSignal(nthreads); + // instantiate Looks used for multi-looking the interferogram isce3::signal::Looks looksObj; @@ -371,6 +377,9 @@ crossmul(isce3::io::Raster& refSlcRaster, std::valarray> refAzimuthSpectrum; std::valarray> secAzimuthSpectrum; + // Kaiser filter to compensate the range windowing effects + std::valarray> filterKaiser; + if (_doCommonAzimuthBandFilter) { // Allocate storage for azimuth spectrum refAzimuthSpectrum.resize(spectrumSize); @@ -384,6 +393,19 @@ crossmul(isce3::io::Raster& refSlcRaster, // Compute the range frequency for each pixel fftfreq(1.0/_rangeSamplingFrequency, rangeFrequencies); + // Harde coded here to build the Kaiser window to + // compensate the windowing effects in range direction + filterKaiser.resize(fft_size); + const double beta = 1.6; + const double dt = 1.0/_rangeSamplingFrequency; + const double bessel_i0_beta = isce3::math::bessel_i0(beta); + for (size_t i = 0; i < rangeFrequencies.size(); ++i){ + double fre = rangeFrequencies[i]; + double tmp = 2.0 * fre * dt; + double kaiserCoefficient = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); + filterKaiser[i] = std::complex(kaiserCoefficient/bessel_i0_beta, 0.0); + } + // Construct the FFTW plan for both geometryIfgram and its conjugation geometryIfgramSignal.forwardRangeFFT(geometryIfgram, refSpectrum, fft_size, linesPerBlock); @@ -394,6 +416,16 @@ crossmul(isce3::io::Raster& refSlcRaster, fft_size, linesPerBlock); geometryIfgramConjSignal.inverseRangeFFT(secSpectrum, geometryIfgramConj, fft_size, linesPerBlock); + + refWindowSignal.forwardRangeFFT(refSlc, refSpectrum, + fft_size, linesPerBlock); + refWindowSignal.inverseRangeFFT(refSpectrum, refSlc, + fft_size, linesPerBlock); + + secWindowSignal.forwardRangeFFT(secSlc, secSpectrum, + fft_size, linesPerBlock); + secWindowSignal.inverseRangeFFT(secSpectrum, secSlc, + fft_size, linesPerBlock); } // loop over all blocks @@ -440,39 +472,16 @@ crossmul(isce3::io::Raster& refSlcRaster, } } - //common azimuth band-pass filter the reference and secondary SLCs - //TODO: since there is no windowing is applied in azimuth, no need to revert - //the windowing effects, and the attena pattern coefficents are not stored in the - //SLC yet, will wait for the implementation and revert the attena pattern then - if (_doCommonAzimuthBandFilter) { - std::string filterType = "kaiser"; - double beta = 1.6; - // Construct azimuth common band filter for a block of data of the reference - _processedAzimuthBandwidth += azimuthFilter.constructAzimuthCommonbandFilter( - _refDoppler, _secDoppler, rngOffset, - _azimuthBandwidth, - _prf, beta, refSlc, refAzimuthSpectrum, fft_size, - linesPerBlock, filterType); - azimuthFilter.filter(refSlc, refAzimuthSpectrum); - - // Construct azimuth common band filter for a block of data of the secondary - azimuthFilter.constructAzimuthCommonbandFilter( - _refDoppler, _secDoppler, rngOffset, - _azimuthBandwidth, - _prf, beta, secSlc, secAzimuthSpectrum, fft_size, - linesPerBlock, filterType); - - azimuthFilter.filter(secSlc, secAzimuthSpectrum); - } - // common range band-pass filtering if (_doCommonRangeBandFilter) { - // Some diagnostic messages to make sure everything has been configured // TODO use journal instead of cout std::cout << " - range pixel spacing: " << _rangePixelSpacing << std::endl; std::cout << " - wavelength: " << _wavelength << std::endl; + refWindowSignal.forward(refSlc, refSpectrum); + secWindowSignal.forward(secSlc, secSpectrum); + // Convert range offset from meters to complex one-way phase #pragma omp parallel for for (size_t line = 0; line < blockRowsData; ++line) { @@ -488,8 +497,14 @@ crossmul(isce3::io::Raster& refSlcRaster, std::complex (std::cos(phase), std::sin(phase)); geometryIfgramConj[line*fft_size + col] = std::complex (std::cos(phase), -1.0*std::sin(phase)); + + // Compensate the kaiser windowing effects in range direction + refSpectrum[line*fft_size + col] /= filterKaiser[col]; + secSpectrum[line*fft_size + col] /= filterKaiser[col]; } } + refWindowSignal.inverse(refSpectrum, refSlc); + secWindowSignal.inverse(secSpectrum, secSlc); // Forward FFT to compute topo-dependent spectrum to determine the // frequency shift @@ -503,6 +518,31 @@ crossmul(isce3::io::Raster& refSlcRaster, rangeFrequencies, rangeFilter, linesPerBlock, fft_size); } + //common azimuth band-pass filter the reference and secondary SLCs + //TODO: since there is no windowing is applied in azimuth, no need to revert + //the windowing effects, and the attena pattern coefficents are not stored in the + //SLC yet, will wait for the implementation and revert the attena pattern then + if (_doCommonAzimuthBandFilter) { + std::string filterType = "kaiser"; + double beta = 1.6; + // Construct azimuth common band filter for a block of data of the reference + _processedAzimuthBandwidth += azimuthFilter.constructAzimuthCommonbandFilter( + _refDoppler, _secDoppler, rngOffset, + _azimuthBandwidth, + _prf, beta, refSlc, refAzimuthSpectrum, fft_size, + linesPerBlock, filterType); + azimuthFilter.filter(refSlc, refAzimuthSpectrum); + + // Construct azimuth common band filter for a block of data of the secondary + azimuthFilter.constructAzimuthCommonbandFilter( + _refDoppler, _secDoppler, rngOffset, + _azimuthBandwidth, + _prf, beta, secSlc, secAzimuthSpectrum, fft_size, + linesPerBlock, filterType); + + azimuthFilter.filter(secSlc, secAzimuthSpectrum); + } + // upsample the reference and secondary SLCs if (_oversampleFactor == 1) { refSlcUpsampled = refSlc; From 67f261cb36faf68135d06371008dbb1aa6ae2bfe Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 30 Oct 2023 21:26:27 +0000 Subject: [PATCH 023/106] clean --- cxx/isce3/signal/Crossmul.cpp | 4 ++-- cxx/isce3/signal/Crossmul.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 047ad80af..e602417a2 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -495,8 +495,7 @@ crossmul(isce3::io::Raster& refSlcRaster, geometryIfgram[line*fft_size + col] = std::complex (std::cos(phase), std::sin(phase)); - geometryIfgramConj[line*fft_size + col] = - std::complex (std::cos(phase), -1.0*std::sin(phase)); + geometryIfgramConj[line*fft_size + col] = std::conj(geometryIfgram[line*fft_size + col]); // Compensate the kaiser windowing effects in range direction refSpectrum[line*fft_size + col] /= filterKaiser[col]; @@ -639,6 +638,7 @@ crossmul(isce3::io::Raster& refSlcRaster, } // update the azimuth and range bandwidth after common band filtering + // using the mean bandwidth if (_doCommonRangeBandFilter) _processedRangeBandwidth /= nblocks; if (_doCommonAzimuthBandFilter) _processedAzimuthBandwidth /= nblocks; } diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 89dbe27d7..231b5928c 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -164,7 +164,7 @@ class isce3::signal::Crossmul { inline void getPeakIndex(std::valarray data, size_t &peakIndex); - /** Range common band filtering*/ + /** Range common band filtering and return the new bandwidth*/ double rangeCommonBandFilter(std::valarray> &refSlc, std::valarray> &secSlc, std::valarray> geometryIfgram, From ac0e90dac0d0ae46a35e77a8a9ada5e6a6f8218c Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 30 Oct 2023 21:41:57 +0000 Subject: [PATCH 024/106] address Geoff's comments --- cxx/isce3/signal/Crossmul.cpp | 16 ++++++++-------- cxx/isce3/signal/Crossmul.h | 14 +++++++------- cxx/isce3/signal/Filter.cpp | 6 +++--- python/packages/nisar/workflows/crossmul.py | 3 +++ 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index e602417a2..0a3d5a03d 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -67,8 +67,8 @@ size_t omp_thread_count() { } /** -* @param[in] refSlc a block of the reference SLC to be filtered -* @param[in] secSlc a block of second SLC to be filtered +* @param[in, out] refSlc a block of the reference SLC to be filtered +* @param[in, out] secSlc a block of second SLC to be filtered * @param[in] geometryIfgram a simulated interferogram that contains the geometrical phase due to baseline separation * @param[in] geometryIfgramConj conjugate of geometryIfgram * @param[in] refSpectrum spectrum of geometryIfgramConj in range direction @@ -81,8 +81,8 @@ size_t omp_thread_count() { double isce3::signal::Crossmul:: rangeCommonBandFilter(std::valarray> &refSlc, std::valarray> &secSlc, - std::valarray> geometryIfgram, - std::valarray> geometryIfgramConj, + std::valarray> &geometryIfgram, + std::valarray> &geometryIfgramConj, std::valarray> &refSpectrum, std::valarray> &secSpectrum, std::valarray &rangeFrequencies, @@ -113,8 +113,8 @@ rangeCommonBandFilter(std::valarray> &refSlc, ncols, frequencyShift); - std::cout << " - rangeFrequencyShift : "<< frequencyShift << std::endl; - std::cout << " - range bandwidth: " << _rangeBandwidth << std::endl; + std::cout << " - rangeFrequencyShift (MHz): "<< frequencyShift/1e6 << std::endl; + std::cout << " - range bandwidth (MHz): " << _rangeBandwidth/1e6 << std::endl; // Since the spectrum of the ref and sec SLCs are already aligned, // we design the low-pass filter as a band-pass at zero frequency with @@ -476,8 +476,8 @@ crossmul(isce3::io::Raster& refSlcRaster, if (_doCommonRangeBandFilter) { // Some diagnostic messages to make sure everything has been configured // TODO use journal instead of cout - std::cout << " - range pixel spacing: " << _rangePixelSpacing << std::endl; - std::cout << " - wavelength: " << _wavelength << std::endl; + std::cout << " - range pixel spacing (m): " << _rangePixelSpacing << std::endl; + std::cout << " - wavelength (m): " << _wavelength << std::endl; refWindowSignal.forward(refSlc, refSpectrum); secWindowSignal.forward(secSlc, secSpectrum); diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 231b5928c..23767cbf0 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -55,7 +55,7 @@ class isce3::signal::Crossmul { /** Get range pixel spacing */ inline double rangePixelSpacing() const { return _rangePixelSpacing; } - /** Set Wavelength*/ + /** Set Wavelength in meters*/ inline void wavelength(double wvl) { _wavelength = wvl; } /** Get Wavelength*/ @@ -81,7 +81,7 @@ class isce3::signal::Crossmul { inline bool doCommonAzimuthBandFilter() const { return _doCommonAzimuthBandFilter; } - /** Set azimuth bandwidth */ + /** Set azimuth bandwidth in Hz*/ inline void azimuthBandwidth(double azBandwidth) { _azimuthBandwidth = azBandwidth; } @@ -115,19 +115,19 @@ class isce3::signal::Crossmul { inline bool doFlatten() const { return _doFlatten; } - /** Set pulse repetition frequency (PRF) */ + /** Set pulse repetition frequency (PRF) in Hz */ inline void prf(double prf) { _prf = prf; } /** Get pulse repetition frequency (PRF) */ inline double prf() const { return _prf; } - /** Set range sampling frequency */ + /** Set range sampling frequency in Hz */ inline void rangeSamplingFrequency(double rgSamplingFreq) { _rangeSamplingFrequency = rgSamplingFreq; } /** Get range sampling frequency */ inline double rangeSamplingFrequency() const { return _rangeSamplingFrequency; } - /** Set the range bandwidth */ + /** Set the range bandwidth in Hz*/ inline void rangeBandwidth(double rngBandwidth) { _rangeBandwidth = rngBandwidth; } /** Get the range bandwidth */ @@ -167,8 +167,8 @@ class isce3::signal::Crossmul { /** Range common band filtering and return the new bandwidth*/ double rangeCommonBandFilter(std::valarray> &refSlc, std::valarray> &secSlc, - std::valarray> geometryIfgram, - std::valarray> geometryIfgramConj, + std::valarray> &geometryIfgram, + std::valarray> &geometryIfgramConj, std::valarray> &refSpectrum, std::valarray> &secSpectrum, std::valarray &rangeFrequencies, diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 6bfb67a8d..523b8631b 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -272,7 +272,7 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, indexOfFrequency(dt, fft_size, fL, indL); int indH; indexOfFrequency(dt, fft_size, fH, indH); - std::cout << " - fL: "<< fL << " , fH: " << fH << " indL: " << indL << " , indH: " << indH << std::endl; + // std::cout << " - fL: "<< fL << " , fH: " << fH << " indL: " << indL << " , indH: " << indH << std::endl; // bessel_i0 of beta double bessel_i0_beta = isce3::math::bessel_i0(beta); @@ -526,8 +526,8 @@ constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDop meanDopCenterFreq /= ncols; meanDopCenterFreqShift /= ncols; - std::cout << " - mean doppler center freq:" << meanDopCenterFreq << std::endl; - std::cout << " - mean doppler center freq shift:" << meanDopCenterFreqShift << std::endl; + std::cout << " - mean doppler center freq (Hz):" << meanDopCenterFreq << std::endl; + std::cout << " - mean doppler center freq shift (Hz):" << meanDopCenterFreqShift << std::endl; _signal.forwardAzimuthFFT(signal, spectrum, ncols, nrows); _signal.inverseAzimuthFFT(spectrum, signal, ncols, nrows); diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index 127c1290a..75e88cd5e 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -67,6 +67,9 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', device = isce3.cuda.core.Device(cfg['worker']['gpu_id']) isce3.cuda.core.set_device(device) crossmul = isce3.cuda.signal.Crossmul() + + if do_common_range_band_filter or do_common_azimuth_band_filter: + raise NotImplementedError("Common band filers have not been implemented for GPU") else: crossmul = isce3.signal.Crossmul() # do common range band filter From d8a0e216d894fd2b8c25c32b8799a5ed427f3280 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 30 Oct 2023 21:42:55 +0000 Subject: [PATCH 025/106] remove the vscode files --- .vscode/settings.json | 69 ------------------------------------------- 1 file changed, 69 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 9403e2971..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "files.associations": { - "any": "cpp", - "array": "cpp", - "atomic": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "chrono": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "complex": "cpp", - "condition_variable": "cpp", - "csignal": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "list": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "map": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "regex": "cpp", - "set": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "new": "cpp", - "ostream": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "cinttypes": "cpp", - "typeindex": "cpp", - "typeinfo": "cpp", - "valarray": "cpp", - "variant": "cpp", - "*.icc": "cpp" - } -} \ No newline at end of file From e6acfd749640c044516a26d752ab81e36739d19b Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 13 Nov 2023 22:04:32 +0000 Subject: [PATCH 026/106] add units --- cxx/isce3/signal/Crossmul.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 23767cbf0..e9f07003b 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -49,13 +49,13 @@ class isce3::signal::Crossmul { /** Get doppler LUT for secondary SLC */ inline const isce3::core::LUT1d & secDoppler() const { return _secDoppler; } - /** Set range pixel spacing */ + /** Set range pixel spacing, in meters */ inline void rangePixelSpacing(double rgPxlSpacing) { _rangePixelSpacing = rgPxlSpacing; } - /** Get range pixel spacing */ + /** Get range pixel spacing, in meters */ inline double rangePixelSpacing() const { return _rangePixelSpacing; } - /** Set Wavelength in meters*/ + /** Set Wavelength, in meters*/ inline void wavelength(double wvl) { _wavelength = wvl; } /** Get Wavelength*/ @@ -81,15 +81,15 @@ class isce3::signal::Crossmul { inline bool doCommonAzimuthBandFilter() const { return _doCommonAzimuthBandFilter; } - /** Set azimuth bandwidth in Hz*/ + /** Set azimuth bandwidth, in Hz*/ inline void azimuthBandwidth(double azBandwidth) { _azimuthBandwidth = azBandwidth; } - /** Get azimuth bandwidth */ + /** Get azimuth bandwidth, in Hz */ inline double azimuthBandwidth() const { return _azimuthBandwidth; } - /** Get processed azimuth bandwidth */ + /** Get processed azimuth bandwidth, in Hz */ inline double processedAzimuthBandwidth() const { return _processedAzimuthBandwidth; } @@ -115,22 +115,22 @@ class isce3::signal::Crossmul { inline bool doFlatten() const { return _doFlatten; } - /** Set pulse repetition frequency (PRF) in Hz */ + /** Set pulse repetition frequency (PRF), in Hz */ inline void prf(double prf) { _prf = prf; } - /** Get pulse repetition frequency (PRF) */ + /** Get pulse repetition frequency (PRF), in Hz */ inline double prf() const { return _prf; } - /** Set range sampling frequency in Hz */ + /** Set range sampling frequency, in Hz */ inline void rangeSamplingFrequency(double rgSamplingFreq) { _rangeSamplingFrequency = rgSamplingFreq; } - /** Get range sampling frequency */ + /** Get range sampling frequency, in Hz*/ inline double rangeSamplingFrequency() const { return _rangeSamplingFrequency; } /** Set the range bandwidth in Hz*/ inline void rangeBandwidth(double rngBandwidth) { _rangeBandwidth = rngBandwidth; } - /** Get the range bandwidth */ + /** Get the range bandwidth, in Hz */ inline double rangeBandwidth() const {return _rangeBandwidth; } /** Get processed range bandwidth after common band filter*/ From 7bebe1fa5420f89a69f0b6bc98f57811f0e6ac44 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 13 Nov 2023 23:08:09 +0000 Subject: [PATCH 027/106] add Geoff comments --- .vscode/settings.json | 6 ++++++ cxx/isce3/signal/Crossmul.cpp | 32 +++++++++++--------------------- cxx/isce3/signal/Crossmul.h | 17 ++++++++++------- 3 files changed, 27 insertions(+), 28 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..73683721e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "files.associations": { + "valarray": "cpp", + "*.icc": "cpp" + } +} \ No newline at end of file diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 0a3d5a03d..50174596e 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -59,7 +59,6 @@ void lookdownShiftImpact(size_t oversample, size_t fft_size, size_t blockRows, // Utility function to get number of OpenMP threads // (gcc sometimes has problems with omp_get_num_threads) size_t omp_thread_count() { - // may use the omp_get_num_procs()? size_t n = 0; #pragma omp parallel reduction(+:n) n += 1; @@ -71,8 +70,8 @@ size_t omp_thread_count() { * @param[in, out] secSlc a block of second SLC to be filtered * @param[in] geometryIfgram a simulated interferogram that contains the geometrical phase due to baseline separation * @param[in] geometryIfgramConj conjugate of geometryIfgram -* @param[in] refSpectrum spectrum of geometryIfgramConj in range direction -* @param[in] secSpectrum spectrum of geometryIfgram in range direction +* @param[in, out] refSpectrum spectrum of geometryIfgramConj in range direction +* @param[in, out] secSpectrum spectrum of geometryIfgram in range direction * @param[in] rangeFrequencies frequencies in range direction * @param[in] rngFilter a filter object * @param[in] blockLength number of rows @@ -81,8 +80,8 @@ size_t omp_thread_count() { double isce3::signal::Crossmul:: rangeCommonBandFilter(std::valarray> &refSlc, std::valarray> &secSlc, - std::valarray> &geometryIfgram, - std::valarray> &geometryIfgramConj, + const std::valarray> &geometryIfgram, + const std::valarray> &geometryIfgramConj, std::valarray> &refSpectrum, std::valarray> &secSpectrum, std::valarray &rangeFrequencies, @@ -96,12 +95,12 @@ rangeCommonBandFilter(std::valarray> &refSlc, // Aligning the spectrum of the two SLCs // Shifting the range spectrum of each image according to the local // (slope-dependent) wavenumber. This shift in frequency domain is - // achieved by removing/adding the geometrical (representing topography) + // achieved by removing/adding the geometrical phase (representing topography) // from/to reference and secondary SLCs in time domain. refSlc *= geometryIfgramConj; secSlc *= geometryIfgram; - // range frequency shift + // range frequency shift, in Hz double frequencyShift = 0.0; // determine the frequency shift based on the power spectral density of @@ -255,16 +254,8 @@ crossmul(isce3::io::Raster& refSlcRaster, } // set up the processed azimuth and range bandwidth - if (_doCommonAzimuthBandFilter) { - _processedAzimuthBandwidth = 0.0; - } else { - _processedAzimuthBandwidth = _azimuthBandwidth; - } - if (_doCommonRangeBandFilter) { - _processedRangeBandwidth = 0.0; - } else { - _processedRangeBandwidth = _rangeBandwidth; - } + _processedAzimuthBandwidth = _doCommonAzimuthBandFilter ? 0.0 : _azimuthBandwidth; + _processedRangeBandwidth = _doCommonRangeBandFilter ? 0.0 : _rangeBandwidth; // size of not-unsampled valarray const auto spectrumSize = fft_size * linesPerBlock; @@ -396,7 +387,7 @@ crossmul(isce3::io::Raster& refSlcRaster, // Harde coded here to build the Kaiser window to // compensate the windowing effects in range direction filterKaiser.resize(fft_size); - const double beta = 1.6; + const double beta = _windowParameter; const double dt = 1.0/_rangeSamplingFrequency; const double bessel_i0_beta = isce3::math::bessel_i0(beta); for (size_t i = 0; i < rangeFrequencies.size(); ++i){ @@ -523,12 +514,11 @@ crossmul(isce3::io::Raster& refSlcRaster, //SLC yet, will wait for the implementation and revert the attena pattern then if (_doCommonAzimuthBandFilter) { std::string filterType = "kaiser"; - double beta = 1.6; // Construct azimuth common band filter for a block of data of the reference _processedAzimuthBandwidth += azimuthFilter.constructAzimuthCommonbandFilter( _refDoppler, _secDoppler, rngOffset, _azimuthBandwidth, - _prf, beta, refSlc, refAzimuthSpectrum, fft_size, + _prf, _windowParameter, refSlc, refAzimuthSpectrum, fft_size, linesPerBlock, filterType); azimuthFilter.filter(refSlc, refAzimuthSpectrum); @@ -536,7 +526,7 @@ crossmul(isce3::io::Raster& refSlcRaster, azimuthFilter.constructAzimuthCommonbandFilter( _refDoppler, _secDoppler, rngOffset, _azimuthBandwidth, - _prf, beta, secSlc, secAzimuthSpectrum, fft_size, + _prf, _windowParameter, secSlc, secAzimuthSpectrum, fft_size, linesPerBlock, filterType); azimuthFilter.filter(secSlc, secAzimuthSpectrum); diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index e9f07003b..8a2a7323f 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -93,11 +93,14 @@ class isce3::signal::Crossmul { inline double processedAzimuthBandwidth() const { return _processedAzimuthBandwidth; } - /** Set beta parameter for the azimuth common band filter */ - inline void beta(double beta) { _beta = beta; } + /** Set beta parameter for the azimuth common band filter + The meaning of this parameter depends on the `window_type`. + For a raised-cosine window, it is the pedestal height of the window. + For a Kaiser window, it is the beta parameter.*/ + inline void windowParameter(double windowParameter) { _windowParameter = windowParameter; } /** Get beta parameter for the azimuth common band filter */ - inline double beta() const { return _beta; } + inline double windowParameter() const { return _windowParameter; } /** Set common range band filtering flag */ inline void doCommonRangeBandFilter(bool doRgBandFilter) { @@ -167,8 +170,8 @@ class isce3::signal::Crossmul { /** Range common band filtering and return the new bandwidth*/ double rangeCommonBandFilter(std::valarray> &refSlc, std::valarray> &secSlc, - std::valarray> &geometryIfgram, - std::valarray> &geometryIfgramConj, + const std::valarray> &geometryIfgram, + const std::valarray> &geometryIfgramConj, std::valarray> &refSpectrum, std::valarray> &secSpectrum, std::valarray &rangeFrequencies, @@ -209,8 +212,8 @@ class isce3::signal::Crossmul { // Processed azimuth bandwidth after the common band filtering double _processedAzimuthBandwidth; - // Beta parameter for constructing common azimuth band filter - double _beta = 0.25; + // Window parameter for constructing common azimuth band filter + double _windowParameter = 1.6; // Flag for common range band filtering bool _doCommonRangeBandFilter = false; From 6dba408cebea7c7d2527a898435a7f16349a1ce8 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 13 Nov 2023 23:08:36 +0000 Subject: [PATCH 028/106] delete .vscode --- .vscode/settings.json | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 73683721e..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "files.associations": { - "valarray": "cpp", - "*.icc": "cpp" - } -} \ No newline at end of file From 4b509a83598c066ad705aafded51fdb45ddcff6e Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 14 Nov 2023 00:01:14 +0000 Subject: [PATCH 029/106] make the window type tunable --- .vscode/settings.json | 68 +++++++++++++++++++ cxx/isce3/signal/Crossmul.cpp | 4 +- cxx/isce3/signal/Crossmul.h | 18 ++++- .../pybind_isce3/signal/Crossmul.cpp | 6 ++ 4 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..b4cc99834 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,68 @@ +{ + "files.associations": { + "complex": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "condition_variable": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "set": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "valarray": "cpp", + "variant": "cpp" + } +} \ No newline at end of file diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 50174596e..385700680 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -121,7 +121,7 @@ rangeCommonBandFilter(std::valarray> &refSlc, std::valarray filterCenterFrequency{0.0}; std::valarray filterBandwidth{_rangeBandwidth - fabs(frequencyShift)}; - std::string filterType = "kaiser"; + std::string filterType = _windowType; // Contruct the low pass filter for this block. This filter is // common for both SLCs @@ -513,7 +513,7 @@ crossmul(isce3::io::Raster& refSlcRaster, //the windowing effects, and the attena pattern coefficents are not stored in the //SLC yet, will wait for the implementation and revert the attena pattern then if (_doCommonAzimuthBandFilter) { - std::string filterType = "kaiser"; + std::string filterType = _windowType; // Construct azimuth common band filter for a block of data of the reference _processedAzimuthBandwidth += azimuthFilter.constructAzimuthCommonbandFilter( _refDoppler, _secDoppler, rngOffset, diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 8a2a7323f..2d4091b7a 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -93,15 +93,21 @@ class isce3::signal::Crossmul { inline double processedAzimuthBandwidth() const { return _processedAzimuthBandwidth; } - /** Set beta parameter for the azimuth common band filter + /** Set window parameter for the azimuth common band filter The meaning of this parameter depends on the `window_type`. For a raised-cosine window, it is the pedestal height of the window. For a Kaiser window, it is the beta parameter.*/ inline void windowParameter(double windowParameter) { _windowParameter = windowParameter; } - /** Get beta parameter for the azimuth common band filter */ + /** Get window parameter for the azimuth common band filter */ inline double windowParameter() const { return _windowParameter; } + /** Get window type for the azimuth common band filter */ + inline std::string windowType() const { return _windowType; } + + /** Set the window type */ + inline void windowType(std::string windowType) { _windowType = windowType; } + /** Set common range band filtering flag */ inline void doCommonRangeBandFilter(bool doRgBandFilter) { _doCommonRangeBandFilter = doRgBandFilter; } @@ -167,7 +173,10 @@ class isce3::signal::Crossmul { inline void getPeakIndex(std::valarray data, size_t &peakIndex); - /** Range common band filtering and return the new bandwidth*/ + /** Range common band filtering and return the new bandwidth + The method is refering to the ESA InSAR tutorial part B. + (https://www.esa.int/esapub/tm/tm19/TM-19_ptB.pdf on page 19) + */ double rangeCommonBandFilter(std::valarray> &refSlc, std::valarray> &secSlc, const std::valarray> &geometryIfgram, @@ -212,6 +221,9 @@ class isce3::signal::Crossmul { // Processed azimuth bandwidth after the common band filtering double _processedAzimuthBandwidth; + // + std::string _windowType = "kaiser"; + // Window parameter for constructing common azimuth band filter double _windowParameter = 1.6; diff --git a/python/extensions/pybind_isce3/signal/Crossmul.cpp b/python/extensions/pybind_isce3/signal/Crossmul.cpp index d0912091e..af34388ef 100644 --- a/python/extensions/pybind_isce3/signal/Crossmul.cpp +++ b/python/extensions/pybind_isce3/signal/Crossmul.cpp @@ -58,6 +58,12 @@ void addbinding(py::class_ & pyCrossmul) .def_property("range_pixel_spacing", py::overload_cast<>(&Crossmul::rangePixelSpacing, py::const_), py::overload_cast(&Crossmul::rangePixelSpacing)) + .def_property("window_parameter", + py::overload_cast<>(&Crossmul::windowParameter, py::const_), + py::overload_cast(&Crossmul::windowParameter)) + .def_property("window_type", + py::overload_cast<>(&Crossmul::windowType, py::const_), + py::overload_cast(&Crossmul::windowType)) .def_property("do_common_range_band_filter", py::overload_cast<>(&Crossmul::doCommonRangeBandFilter, py::const_), py::overload_cast(&Crossmul::doCommonRangeBandFilter)) From 7902d83d1fa6c2e37fc69d2980ad8439f3d44847 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 15 Nov 2023 22:27:01 +0000 Subject: [PATCH 030/106] change minors --- .vscode/settings.json | 68 ------------------------------- cxx/isce3/signal/Crossmul.cpp | 22 +++++----- cxx/isce3/signal/Crossmul.h | 20 ++++----- cxx/isce3/signal/Filter.cpp | 2 +- tests/cxx/isce3/signal/filter.cpp | 14 +++---- 5 files changed, 28 insertions(+), 98 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index b4cc99834..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "files.associations": { - "complex": "cpp", - "any": "cpp", - "array": "cpp", - "atomic": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "chrono": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "condition_variable": "cpp", - "csignal": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "list": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "map": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "regex": "cpp", - "set": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "new": "cpp", - "ostream": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "cinttypes": "cpp", - "typeindex": "cpp", - "typeinfo": "cpp", - "valarray": "cpp", - "variant": "cpp" - } -} \ No newline at end of file diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 385700680..d01c862a9 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -117,7 +117,7 @@ rangeCommonBandFilter(std::valarray> &refSlc, // Since the spectrum of the ref and sec SLCs are already aligned, // we design the low-pass filter as a band-pass at zero frequency with - // bandwidth of (W - frequency shift) + // bandwidth of (range bandwidth - frequency shift) std::valarray filterCenterFrequency{0.0}; std::valarray filterBandwidth{_rangeBandwidth - fabs(frequencyShift)}; @@ -272,10 +272,8 @@ crossmul(isce3::io::Raster& refSlcRaster, // storage for a block of range offsets std::valarray rngOffset(spectrumSize); - // storage for a simulated interferogram which its phase is the - // interferometric phase due to the imaging geometry: - // phase = (4*PI/wavelength)*(rangePixelSpacing)*(rngOffset) - + // InSAR phase due to topography + // geometryIfgram = (4*PI/wavelength)*(rangePixelSpacing)*(rngOffset) std::valarray> geometryIfgram; // complex conjugate of geometryIfgram @@ -453,7 +451,7 @@ crossmul(isce3::io::Raster& refSlcRaster, secSlc[std::slice(line*fft_size, ncols, 1)] = dataLine; } - // load the range offsets that are required by the flatten, + // load the range offsets that are required by flattening, // common range and azimuth filters if (_doFlatten || _doCommonAzimuthBandFilter || _doCommonRangeBandFilter) { std::valarray offsetLine(ncols); @@ -473,13 +471,12 @@ crossmul(isce3::io::Raster& refSlcRaster, refWindowSignal.forward(refSlc, refSpectrum); secWindowSignal.forward(secSlc, secSpectrum); - // Convert range offset from meters to complex one-way phase + // Convert range offset from meters to complex one-way geometric phase #pragma omp parallel for for (size_t line = 0; line < blockRowsData; ++line) { for (size_t col = 0; col < ncols; ++col) { - // Use the one-way phase instead of the two-way phase - // to align the spectrum and determine the frequency shifts + // one-way geometric phase to shift the spectrum double phase = 2.0 * M_PI * _rangePixelSpacing*rngOffset[line*fft_size+col] / _wavelength; @@ -488,7 +485,7 @@ crossmul(isce3::io::Raster& refSlcRaster, std::complex (std::cos(phase), std::sin(phase)); geometryIfgramConj[line*fft_size + col] = std::conj(geometryIfgram[line*fft_size + col]); - // Compensate the kaiser windowing effects in range direction + // Compensate the kaiser windowing effects along the range direction refSpectrum[line*fft_size + col] /= filterKaiser[col]; secSpectrum[line*fft_size + col] /= filterKaiser[col]; } @@ -496,7 +493,7 @@ crossmul(isce3::io::Raster& refSlcRaster, refWindowSignal.inverse(refSpectrum, refSlc); secWindowSignal.inverse(secSpectrum, secSlc); - // Forward FFT to compute topo-dependent spectrum to determine the + // Forward FFT to compute geometry-dependent spectrum to determine the // frequency shift geometryIfgramConjSignal.forward(geometryIfgramConj, refSpectrum); geometryIfgramSignal.forward(geometryIfgram, secSpectrum); @@ -509,8 +506,9 @@ crossmul(isce3::io::Raster& refSlcRaster, } //common azimuth band-pass filter the reference and secondary SLCs + //refering to ESA InSAR tutorial-part B (https://www.esa.int/esapub/tm/tm19/TM-19_ptB.pdf on page 20 and 21) //TODO: since there is no windowing is applied in azimuth, no need to revert - //the windowing effects, and the attena pattern coefficents are not stored in the + //the windowing effects, and the antenna pattern coefficients are not stored in the //SLC yet, will wait for the implementation and revert the attena pattern then if (_doCommonAzimuthBandFilter) { std::string filterType = _windowType; diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 2d4091b7a..f9b9557cf 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -195,10 +195,10 @@ class isce3::signal::Crossmul { //Doppler LUT for the secondary SLC isce3::core::LUT1d _secDoppler; - // range pixel spacing + // range pixel spacing in meters double _rangePixelSpacing; - // radar wavelength + // radar wavelength in meters double _wavelength; // number of range looks @@ -215,31 +215,31 @@ class isce3::signal::Crossmul { // Flag for common azimuth band filtering bool _doCommonAzimuthBandFilter = false; - // Azimuth bandwidth + // Azimuth bandwidth in Hz double _azimuthBandwidth; - // Processed azimuth bandwidth after the common band filtering + // Processed azimuth bandwidth after the common band filtering in Hz double _processedAzimuthBandwidth; - // + // Window type std::string _windowType = "kaiser"; - // Window parameter for constructing common azimuth band filter + // Window parameter for constructing common band filter double _windowParameter = 1.6; // Flag for common range band filtering bool _doCommonRangeBandFilter = false; - //pulse repetition frequency + //pulse repetition frequency, in Hz double _prf; - // range samping frequency + // range samping frequency, in Hz double _rangeSamplingFrequency; - // range signal bandwidth + // range signal bandwidth in Hz double _rangeBandwidth; - // Processed range bandwidth after the common band filtering + // Processed range bandwidth after the common band filtering in Hz double _processedRangeBandwidth; // number of lines per block diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 523b8631b..e88eec320 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -156,7 +156,7 @@ constructRangeBandpassBoxcar(std::valarray subBandCenterFrequencies, int fft_size, std::valarray>& _filter1D) { - // construct a boxcar bandpass filter in frequency domian + // construct a boxcar bandpass filter in frequency domain // which may have several bands defined by centerferquencies and // subBandBandwidths for (size_t i = 0; i filter; filter.constructAzimuthCommonbandCosineFilter(dop1, - dop2, - rangeOffsets, - commonAzimuthBandwidth, - prf, - beta, - refSlc, refSpectrum, - ncols, blockRows); + dop2, + rangeOffsets, + commonAzimuthBandwidth, + prf, + beta, + refSlc, refSpectrum, + ncols, blockRows); filter.writeFilter(ncols, blockRows); } From 787063d9ae7cd3eae52d133a9789b802aa02ce32 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 16 Nov 2023 01:08:44 +0000 Subject: [PATCH 031/106] add kaiser window functions --- .vscode/settings.json | 69 ++++++++++++++++++++++++++ cxx/isce3/signal/Filter.cpp | 97 +++++++++++++++++++++++++++++++++++-- cxx/isce3/signal/Filter.h | 21 ++++++++ 3 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..9403e2971 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,69 @@ +{ + "files.associations": { + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "set": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "valarray": "cpp", + "variant": "cpp", + "*.icc": "cpp" + } +} \ No newline at end of file diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index e88eec320..15dd11a55 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -68,16 +68,15 @@ constructRangeBandpassFilter(double rangeSamplingFrequency, size_t nrows, std::string filterType) { + _signal.forwardRangeFFT(signal, spectrum, ncols, nrows); + _signal.inverseRangeFFT(spectrum, signal, ncols, nrows); + constructRangeBandpassFilter(rangeSamplingFrequency, subBandCenterFrequencies, subBandBandwidths, ncols, nrows, filterType); - - _signal.forwardRangeFFT(signal, spectrum, ncols, nrows); - _signal.inverseRangeFFT(spectrum, signal, ncols, nrows); - } template @@ -613,6 +612,96 @@ writeFilter(size_t ncols, size_t nrows) } +/** + * @param[in] ripple Upper bound for the deviation (in dB) of the magnitude of the filter's frequency response from that of the desired filter (not including frequencies in any transition intervals). + * @param[in] width Width of transition region, normalized so that 1 corresponds to pi radians / sample. + * @param[out] n the length of the Kaiser window. + * @param[out] beta the beta parameter for the Kaiser window + */ +template +void +isce3::signal::Filter::_getKaiserord(const double ripple, const double width, + int &n, double &beta) +{ + double A = std::abs(ripple) // in case somebody is confused as to what's meant + if (A < 8) { + // Formula for N is not valid in this range. + std::cout << "Requested maximum ripple attentuation " << A + << " is too small for the Kaiser formula.\n"; + + throw isce3::except::InvalidArgument(ISCE_SRCINFO(), + "Requested maximum ripple attentuation is too small for the Kaiser formula."); + } + + // Kaiser's formula (as given in Oppenheim and Schafer) is for the filter + // order, so we have to add 1 to get the number of taps. + double numtaps = (A - 7.95) / 2.285 / (M_PI * width) + 1; + + n = int(std::ceil(numtaps)); + beta = _kaiser_beta(A); +} + +/** + * @param[in] ripple The desired attenuation in the stopband and maximum ripple in the passband, in dB. + */ +template +double +isce3::signal::Filter::_kaiser_beta(const double ripple) +{ + if (ripple > 50) { + return 0.1102 * (ripple - 8.7); + } + else if (ripple > 21){ + return 0.5842 * (ripple - 21) ** 0.4 + 0.07886 * (ripple - 21); + } + else { + return 0.0; + } +} + +/** + * @param[in] stopatt Upper bound for the deviation (in dB) of the magnitude of the filter's frequency response from that of the desired filter (not including frequencies in any transition intervals). + * @param[in] transition_width Width of transition region, normalized so that 1 corresponds to pi radians / sample. + * @param[in] force_odd_len Force to be odd lenght + * @param[out] n the length of the Kaiser window. + * @param[out] beta the beta parameter for the Kaiser window + * @param[out] t time samples for Kaiser filter design method + */ +template +void +isce3::signal::Filter::_kaiser_design(const double stopatt, + const double transition_width, + const bool force_odd_len, + int &n, + double &beta, + std::valarray &t) +{ + _kaiserord(stopatt, transition_width, n, beta); + if (force_odd_len && (n % 2 == 0)) n += 1; + + t.resize(n); + for (size_t i = 0; i < t.size(); i++) t[i] = i - (n - 1) / 2.0; +} +/** + * @param[in] t time samples for Kaiser filter design method + * @param[in] beta the beta parameter for the Kaiser window + * @param[out] irf time samples for Kaiser filter design method + */ +template +void +isce3::signal::Filter::_kaiser_irf(const std::valarray &t, + const double beta, + std::valarray &irf) +{ + double alpha = beta / M_PI; + double beta0 = isce3::math::bessel_i0(beta); + for (size_t i = 0; i < t.size(); i++) { + std::complex val(t[i] * t[i] - alpha * alpha, 0.0); + irf[i].real = isce3::math::sinc(std::sqrt(val).real) / beta0; + irf[i].imag = 0.0; + } +} + template class isce3::signal::Filter; template class isce3::signal::Filter; diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index dac4157b5..1c08f1ccf 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -134,6 +134,27 @@ class isce3::signal::Filter { void writeFilter(size_t ncols, size_t nrows); + private: + /** Determine the filter window parameters for the Kaiser window method*/ + void _getKaiserord(const double ripple, const double width, + int &n, double &beta); + + /** Compute the Kaiser parameter `beta`, given the attenuation 'ripple`*/ + double _kaiser_beta(const double ripple); + + /** Return length, shape, and time samples for Kaiser filter design method*/ + void _kaiser_design(const double stopatt, + const double transition_width, + const bool force_odd_len, + int &n, + double &beta, + std::valarray &t); + + /** Impulse response (Fourier transform) of Kaiser window*/ + void _kaiser_irf(const std::valarray &t, + const double beta, + std::valarray &irf); + private: isce3::signal::Signal _signal; std::valarray> _filter; From 7e36fedb686f7d76b2ace489577fa1f36313d854 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 16 Nov 2023 19:56:10 +0000 Subject: [PATCH 032/106] finish translating the python to C++ --- cxx/isce3/signal/Filter.cpp | 114 ++++++++++++++++++++++++++++++++---- cxx/isce3/signal/Filter.h | 22 ++++++- 2 files changed, 124 insertions(+), 12 deletions(-) diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 15dd11a55..992de78ec 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -623,7 +623,7 @@ void isce3::signal::Filter::_getKaiserord(const double ripple, const double width, int &n, double &beta) { - double A = std::abs(ripple) // in case somebody is confused as to what's meant + const double A = std::abs(ripple) // in case somebody is confused as to what's meant if (A < 8) { // Formula for N is not valid in this range. std::cout << "Requested maximum ripple attentuation " << A @@ -635,7 +635,7 @@ isce3::signal::Filter::_getKaiserord(const double ripple, const double width, // Kaiser's formula (as given in Oppenheim and Schafer) is for the filter // order, so we have to add 1 to get the number of taps. - double numtaps = (A - 7.95) / 2.285 / (M_PI * width) + 1; + const double numtaps = (A - 7.95) / 2.285 / (M_PI * width) + 1; n = int(std::ceil(numtaps)); beta = _kaiser_beta(A); @@ -662,7 +662,7 @@ isce3::signal::Filter::_kaiser_beta(const double ripple) /** * @param[in] stopatt Upper bound for the deviation (in dB) of the magnitude of the filter's frequency response from that of the desired filter (not including frequencies in any transition intervals). * @param[in] transition_width Width of transition region, normalized so that 1 corresponds to pi radians / sample. - * @param[in] force_odd_len Force to be odd lenght + * @param[in] force_odd_len Force to be odd length * @param[out] n the length of the Kaiser window. * @param[out] beta the beta parameter for the Kaiser window * @param[out] t time samples for Kaiser filter design method @@ -679,9 +679,10 @@ isce3::signal::Filter::_kaiser_design(const double stopatt, _kaiserord(stopatt, transition_width, n, beta); if (force_odd_len && (n % 2 == 0)) n += 1; - t.resize(n); + if (t.size() <= 0) t.resize(n); for (size_t i = 0; i < t.size(); i++) t[i] = i - (n - 1) / 2.0; } + /** * @param[in] t time samples for Kaiser filter design method * @param[in] beta the beta parameter for the Kaiser window @@ -691,14 +692,107 @@ template void isce3::signal::Filter::_kaiser_irf(const std::valarray &t, const double beta, - std::valarray &irf) + std::valarray> &irf) { - double alpha = beta / M_PI; - double beta0 = isce3::math::bessel_i0(beta); + const double alpha = beta / M_PI; + const double beta0 = isce3::math::bessel_i0(beta); + + if (irf.size() <= 0) irf.resize(t.size()); for (size_t i = 0; i < t.size(); i++) { - std::complex val(t[i] * t[i] - alpha * alpha, 0.0); - irf[i].real = isce3::math::sinc(std::sqrt(val).real) / beta0; - irf[i].imag = 0.0; + std::complex val(t[i] * t[i] - alpha * alpha, 0.0); + irf[i] = std::complex(isce3::math::sinc(std::sqrt(val).real) / beta0, 0.0); + } +} + +/** + * @param[in] n the length of the Kaiser window. + * @param[in] beta the beta parameter for the Kaiser window + * @param[out] kaiser_window time samples for Kaiser filter design method + */ +template +void +isce3::signal::Filter::_kaiser(const int n, + const double beta, + std::valarray> &kaiser_window) +{ + const double beta0 = isce3::math::bessel_i0(beta) * n; + + if (kaiser_window.size() <= 0) kaiser_window.resize(n); + + for (size_t i = 0; i < n; i++) { + const double t = i - (n - 1) / 2.0; + if (std::abs(t) <= n / 2.0) kaiser_window[i] = isce3::math::bessel_i0( + beta * std::sqrt(1.0 - (2 * t / n) * (2 * t / n))) / beta0; + } +} + +/** + * @param[in] kaiser_window the Kaiser window. + * @param[in] fc the center frequency + * @param[out] shifted_kaiser_window shifted kaiser window with center frequency fc + */ +template +void +isce3::signal::Filter::_lowpass2bandpass(const std::valarray> &kaiser_window, + const double fc, + std::valarray> &shifted_kaiser_window) +{ + if (shifted_kaiser_window.size() <= 0) shifted_kaiser_window.resize(kaiser_window.size()); + const int n = kaiser_window.size(); + for (size_t i = 0; i < n; i++) { + const double t = i - (n - 1) / 2.0; + const double phase = 2.0 * M_PI * fc * t; + const std::complex ramp_phase(std::cos(phase), std::sin(phase)); + shifted_kaiser_window[i] = kaiser_window[i] * ramp_phase; + } +} + +/** + * @param[in] bandwidth the signal bandwidth + * @param[in] fs the sampling frequency + * @param[in] beta the Kaiser window beta parameter. + * @param[in] stopatt Upper bound for the deviation (in dB) of the magnitude of the filter's frequency response from that of the desired filter (not including frequencies in any transition intervals). + * @param[in] transition_width transition width [0-1] + * @param[in] force_odd_len Force to be odd length + * @param[out] kaiser_window low bandpass kaiser window + */ +template +void +isce3::signal::Filter::_design_shaped_lowpass_filter(const double bandwidth, + const double fs, + const double beta, + std::valarray> &kaiser_window, + const double stopatt, + const double transition_width, + const bool force_odd_len) +{ + // Normalized bandwdith + const double bw = bandwidth / fs; + + // Transition width is specified in terms of output bandwidth, so scale to + // get width at sample rate of filter. + const double tw = transition_width * bw; + + if ((bw + tw / 2.0) > 1.0) { + std::cout << "Passband + transition cannot exceed Nyquist\n"; + throw isce3::except::InvalidArgument(ISCE_SRCINFO(), + "Passband + transition cannot exceed Nyquist"); + } + + int n = 0; + double beta = 0.0; + std::valarray t; + std::valarray> irf; + std::valarray> kaiser; + + _kaiser_design(stopatt, tw, force_odd_len, n, beta, t); + _kaiser_irf(t * bw, beta, irf); + _kaiser(n, beta, kaiser); + + if (kaiser_window.size() <= 0) kaiser_window.resize(n); + + for (size_t i = 0; i < n; i++) { + kaiser_window[i] = irf[i] * kaiser[i] * bw; } } diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index 1c08f1ccf..078a9dc31 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -153,8 +153,26 @@ class isce3::signal::Filter { /** Impulse response (Fourier transform) of Kaiser window*/ void _kaiser_irf(const std::valarray &t, const double beta, - std::valarray &irf); - + std::valarray> &irf); + + /** Kaiser window with length n*/ + void _kaiser(const int n, + const double beta, + std::valarray> &kaiser_window); + + /** Turn a low pass filter into a band pass filter by applying a phase ramp.*/ + void _lowpass2bandpass(const std::valarray> &kaiser_window, + const double fc, + std::valarray> &shifted_kaiser_window); + + /** Design a low pass filter having a passband shaped like a window using the Kaiser method*/ + void _design_shaped_lowpass_filter(const double bandwidth, + const double fs, + const double beta, + std::valarray> &kaiser_window, + const double stopatt = 40.0, + const double transition_width = 0.15, + const bool force_odd_len = false); private: isce3::signal::Signal _signal; std::valarray> _filter; From 86bbee48f0a97357470228b22f0ecd74c4bfc766 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 16 Nov 2023 23:09:20 +0000 Subject: [PATCH 033/106] finish the translation --- cxx/isce3/signal/Filter.cpp | 18 ++++++------- cxx/isce3/signal/Filter.h | 53 +++++++++++++++++++------------------ 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 992de78ec..7de314628 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -620,10 +620,10 @@ writeFilter(size_t ncols, size_t nrows) */ template void -isce3::signal::Filter::_getKaiserord(const double ripple, const double width, +isce3::signal::Filter::_kaiserord(const double ripple, const double width, int &n, double &beta) { - const double A = std::abs(ripple) // in case somebody is confused as to what's meant + const double A = std::abs(ripple); // in case somebody is confused as to what's meant if (A < 8) { // Formula for N is not valid in this range. std::cout << "Requested maximum ripple attentuation " << A @@ -652,7 +652,7 @@ isce3::signal::Filter::_kaiser_beta(const double ripple) return 0.1102 * (ripple - 8.7); } else if (ripple > 21){ - return 0.5842 * (ripple - 21) ** 0.4 + 0.07886 * (ripple - 21); + return 0.5842 * std::pow(ripple - 21.0, 0.4) + 0.07886 * (ripple - 21); } else { return 0.0; @@ -700,7 +700,7 @@ isce3::signal::Filter::_kaiser_irf(const std::valarray &t, if (irf.size() <= 0) irf.resize(t.size()); for (size_t i = 0; i < t.size(); i++) { std::complex val(t[i] * t[i] - alpha * alpha, 0.0); - irf[i] = std::complex(isce3::math::sinc(std::sqrt(val).real) / beta0, 0.0); + irf[i] = std::complex(isce3::math::sinc(std::sqrt(val).real()) / beta0, 0.0); } } @@ -715,14 +715,14 @@ isce3::signal::Filter::_kaiser(const int n, const double beta, std::valarray> &kaiser_window) { - const double beta0 = isce3::math::bessel_i0(beta) * n; + const double beta0 = isce3::math::bessel_i0(beta); if (kaiser_window.size() <= 0) kaiser_window.resize(n); for (size_t i = 0; i < n; i++) { const double t = i - (n - 1) / 2.0; if (std::abs(t) <= n / 2.0) kaiser_window[i] = isce3::math::bessel_i0( - beta * std::sqrt(1.0 - (2 * t / n) * (2 * t / n))) / beta0; + beta * std::sqrt(1.0 - (2 * t / (n - 1)) * (2 * t / (n - 1)))) / beta0; } } @@ -760,7 +760,7 @@ template void isce3::signal::Filter::_design_shaped_lowpass_filter(const double bandwidth, const double fs, - const double beta, + const double window_shape, std::valarray> &kaiser_window, const double stopatt, const double transition_width, @@ -786,13 +786,13 @@ isce3::signal::Filter::_design_shaped_lowpass_filter(const double bandwidth, std::valarray> kaiser; _kaiser_design(stopatt, tw, force_odd_len, n, beta, t); - _kaiser_irf(t * bw, beta, irf); + _kaiser_irf(t * bw, window_shape, irf); _kaiser(n, beta, kaiser); if (kaiser_window.size() <= 0) kaiser_window.resize(n); for (size_t i = 0; i < n; i++) { - kaiser_window[i] = irf[i] * kaiser[i] * bw; + kaiser_window[i] = std::complex(bw, 0.0) * irf[i] * kaiser[i]; } } diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index 078a9dc31..c4ddcfb72 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "Signal.h" // Declaration @@ -134,45 +135,45 @@ class isce3::signal::Filter { void writeFilter(size_t ncols, size_t nrows); - private: + public: /** Determine the filter window parameters for the Kaiser window method*/ - void _getKaiserord(const double ripple, const double width, - int &n, double &beta); + void _kaiserord(const double ripple, const double width, + int &n, double &beta); /** Compute the Kaiser parameter `beta`, given the attenuation 'ripple`*/ double _kaiser_beta(const double ripple); /** Return length, shape, and time samples for Kaiser filter design method*/ - void _kaiser_design(const double stopatt, - const double transition_width, - const bool force_odd_len, - int &n, - double &beta, - std::valarray &t); + void _kaiser_design(const double stopatt, + const double transition_width, + const bool force_odd_len, + int &n, + double &beta, + std::valarray &t); /** Impulse response (Fourier transform) of Kaiser window*/ - void _kaiser_irf(const std::valarray &t, - const double beta, - std::valarray> &irf); + void _kaiser_irf(const std::valarray &t, + const double beta, + std::valarray> &irf); - /** Kaiser window with length n*/ - void _kaiser(const int n, - const double beta, - std::valarray> &kaiser_window); + /** Kaiser window with length n*/ + void _kaiser(const int n, + const double beta, + std::valarray> &kaiser_window); - /** Turn a low pass filter into a band pass filter by applying a phase ramp.*/ - void _lowpass2bandpass(const std::valarray> &kaiser_window, + /** Turn a low pass filter into a band pass filter by applying a phase ramp.*/ + void _lowpass2bandpass(const std::valarray> &kaiser_window, const double fc, std::valarray> &shifted_kaiser_window); - /** Design a low pass filter having a passband shaped like a window using the Kaiser method*/ - void _design_shaped_lowpass_filter(const double bandwidth, - const double fs, - const double beta, - std::valarray> &kaiser_window, - const double stopatt = 40.0, - const double transition_width = 0.15, - const bool force_odd_len = false); + /** Design a low pass filter having a passband shaped like a window using the Kaiser method*/ + void _design_shaped_lowpass_filter(const double bandwidth, + const double fs, + const double window_shape, + std::valarray> &kaiser_window, + const double stopatt = 40.0, + const double transition_width = 0.15, + const bool force_odd_len = false); private: isce3::signal::Signal _signal; std::valarray> _filter; From 9dc838fc1afbad7e0b8a229b94fef0acb067d37e Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 21 Nov 2023 00:11:04 +0000 Subject: [PATCH 034/106] using the time domain range kaiser filter --- cxx/isce3/signal/Crossmul.cpp | 17 +++--- cxx/isce3/signal/Filter.cpp | 99 +++++++++++++++++++++++++++++++++++ cxx/isce3/signal/Filter.h | 19 +++++++ 3 files changed, 129 insertions(+), 6 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index d01c862a9..0a3c06215 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -118,34 +118,39 @@ rangeCommonBandFilter(std::valarray> &refSlc, // Since the spectrum of the ref and sec SLCs are already aligned, // we design the low-pass filter as a band-pass at zero frequency with // bandwidth of (range bandwidth - frequency shift) - std::valarray filterCenterFrequency{0.0}; - std::valarray filterBandwidth{_rangeBandwidth - fabs(frequencyShift)}; + const double filterCenterFrequency = 0.0; + const double filterBandwidth = _rangeBandwidth - fabs(frequencyShift); std::string filterType = _windowType; // Contruct the low pass filter for this block. This filter is // common for both SLCs - rngFilter.constructRangeBandpassFilter(_rangeSamplingFrequency, + rngFilter.constructRangeCommonbandFilter(_rangeSamplingFrequency, filterCenterFrequency, filterBandwidth, refSlc, refSpectrum, ncols, blockLength, - filterType); + _windowType, + _windowParameter); + // low pass filter the ref slc rngFilter.filter(refSlc, refSpectrum); // low band pass the sec slc - rngFilter.constructRangeBandpassFilter(_rangeSamplingFrequency, + rngFilter.constructRangeCommonbandFilter(_rangeSamplingFrequency, filterCenterFrequency, filterBandwidth, secSlc, secSpectrum, ncols, blockLength, - filterType); + _windowType, + _windowParameter); + rngFilter.filter(secSlc, secSpectrum); + // restore the original phase without the geometry phase // in case other steps will use the original phase refSlc *= geometryIfgram; diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 7de314628..c8d90fbbb 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -138,6 +138,57 @@ constructRangeBandpassFilter(double rangeSamplingFrequency, } } +/** + * @param[in] rangeSamplingFrequency range sampling frequency + * @param[in] subBandCenterFrequency a vector of center frequencies for each band + * @param[in] subBandBandwidth a vector of bandwidths for each band + * @param[in, out] signal a block of data to filter + * @param[in, out] spectrum a block of spectrum, which is internally used for FFT computations + * @param[in] ncols number of columns of the block of data + * @param[in] nrows number of rows of the block of data + * @param[in] filterType type of the band-pass filter + * @param[in] windowParameter filter parameter + + */ +template +void +isce3::signal::Filter::constructRangeCommonbandFilter(const double rangeSamplingFrequency, + const double subBandCenterFrequency, + const double subBandBandwidth, + std::valarray> &signal, + std::valarray> &spectrum, + size_t ncols, + size_t nrows, + const std::string filterType, + const double windowParameter) +{ + _signal.forwardRangeFFT(signal, spectrum, ncols, nrows); + _signal.inverseRangeFFT(spectrum, signal, ncols, nrows); + + int fft_size = ncols; + + _filter.resize(fft_size*nrows); + std::valarray> _filter1D(fft_size); // + _filter1D = std::complex(0.0,0.0); + + if (filterType=="kaiser"){ + constructRangeCommonbandKaiserFilter(subBandCenterFrequency, + subBandBandwidth, + rangeSamplingFrequency, + fft_size, + windowParameter, + _filter1D); + } else { + std::cout << filterType << " filter has not been implemented" << std::endl; + } + + //construct a block of the filter + for (size_t line = 0; line < nrows; line++ ){ + for (size_t col = 0; col < fft_size; col++ ){ + _filter[line*fft_size+col] = _filter1D[col]; + } + } +} /** * @param[in] subBandCenterFrequencies a vector of center frequencies for each band @@ -235,6 +286,54 @@ constructRangeBandpassCosine(std::valarray subBandCenterFrequencies, } } +/** + * @param[in] subBandCenterFrequencies a vector of center frequencies for each band + * @param[in] subBandBandwidths a vector of bandwidths for each band + * @param[in] rangeSamplingFrequency samplig rate of the signal + * @param[in] fft_size length of the spectrum + * @param[in] beta parameter for the kaiser filter (normally set 2.5) + * @param[out] filter1D one dimensional boxcar bandpass filter in frequency domain + */ +template +void +isce3::signal::Filter:: +constructRangeCommonbandKaiserFilter(const double subBandCenterFrequency, + const double subBandBandwidth, + const double rangeSamplingFrequency, + const int fft_size, + const double beta, + std::valarray>& filter1D) +{ + + isce3::signal::Signal signal; + signal.forwardRangeFFT(filter1D, filter1D, fft_size, 1); + + std::valarray> kaiser; + std::valarray> shiftedKaiser; + _design_shaped_lowpass_filter(subBandBandwidth, rangeSamplingFrequency, beta, kaiser); + + // Turn into bandpass filter + _lowpass2bandpass(kaiser, subBandCenterFrequency, shiftedKaiser); + + // Zero padding the filter on sides + const int sizeOfKaiser = shiftedKaiser.size(); + const int startInd = (fft_size - sizeOfKaiser) / 2; + const std::complex maxVal = std::abs(shiftedKaiser).max(); + + if (startInd <= sizeOfKaiser) { + std::cout << "FFT size is less than the window size\n"; + throw isce3::except::InvalidArgument(ISCE_SRCINFO(), + "FFT size is less than the window size"); + } + + // Zero padding the filter + for (size_t ind = startInd; ind < startInd + sizeOfKaiser; ind ++) { + filter1D[ind] = shiftedKaiser[ind - startInd] / maxVal; + } + // Transform to frequency domain + signal.forward(filter1D, filter1D); +} + /** * @param[in] subBandCenterFrequencies a vector of center frequencies for each band * @param[in] subBandBandwidths a vector of bandwidths for each band diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index c4ddcfb72..fd7a6cd77 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -89,6 +89,25 @@ class isce3::signal::Filter { double beta, std::valarray>& _filter1D); + /** Construct the range common band filter*/ + void constructRangeCommonbandFilter(const double rangeSamplingFrequency, + const double subBandCenterFrequency, + const double subBandBandwidths, + std::valarray> &signal, + std::valarray> &spectrum, + size_t ncols, + size_t nrows, + const std::string filterType, + const double windowParameter); + + /** Construct a kaiser common band range band-pass filter for one band*/ + void constructRangeCommonbandKaiserFilter(const double subBandCenterFrequency, + const double subBandBandwidth, + const double rangeSamplingFrequency, + const int fft_size, + const double beta, + std::valarray>& filter1D); + /** Construct azimuth common band filter*/ double constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, const isce3::core::LUT1d & secDoppler, From aa558371a62d935ff636f713f80b6fdac323139b Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 21 Nov 2023 00:45:33 +0000 Subject: [PATCH 035/106] revert the kaiser window effects --- cxx/isce3/signal/Crossmul.cpp | 30 +++++++++++++----------------- cxx/isce3/signal/Filter.cpp | 13 ++++++++++++- cxx/isce3/signal/Filter.h | 2 ++ 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 0a3c06215..77b001bc6 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -371,9 +371,9 @@ crossmul(isce3::io::Raster& refSlcRaster, std::valarray> refAzimuthSpectrum; std::valarray> secAzimuthSpectrum; - // Kaiser filter to compensate the range windowing effects - std::valarray> filterKaiser; - + // retrieve the original filter to revert the range windowing effects + std::valarray> originalRangeFilter(std::complex(1.0, 0.0), + fft_size); if (_doCommonAzimuthBandFilter) { // Allocate storage for azimuth spectrum refAzimuthSpectrum.resize(spectrumSize); @@ -387,18 +387,12 @@ crossmul(isce3::io::Raster& refSlcRaster, // Compute the range frequency for each pixel fftfreq(1.0/_rangeSamplingFrequency, rangeFrequencies); - // Harde coded here to build the Kaiser window to + // For NISAR, build the Kaiser window to // compensate the windowing effects in range direction - filterKaiser.resize(fft_size); - const double beta = _windowParameter; - const double dt = 1.0/_rangeSamplingFrequency; - const double bessel_i0_beta = isce3::math::bessel_i0(beta); - for (size_t i = 0; i < rangeFrequencies.size(); ++i){ - double fre = rangeFrequencies[i]; - double tmp = 2.0 * fre * dt; - double kaiserCoefficient = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); - filterKaiser[i] = std::complex(kaiserCoefficient/bessel_i0_beta, 0.0); - } + // TODO: this function is sensor dependent! + rangeFilter.constructRangeCommonbandKaiserFilter(0.0, _rangeBandwidth, + _rangeSamplingFrequency, + fft_size, 1.6, originalRangeFilter); // Construct the FFTW plan for both geometryIfgram and its conjugation geometryIfgramSignal.forwardRangeFFT(geometryIfgram, refSpectrum, @@ -490,9 +484,11 @@ crossmul(isce3::io::Raster& refSlcRaster, std::complex (std::cos(phase), std::sin(phase)); geometryIfgramConj[line*fft_size + col] = std::conj(geometryIfgram[line*fft_size + col]); - // Compensate the kaiser windowing effects along the range direction - refSpectrum[line*fft_size + col] /= filterKaiser[col]; - secSpectrum[line*fft_size + col] /= filterKaiser[col]; + // revert the original windowing effects along the slant range direction + if (std::abs(originalRangeFilter[col]) > 1e-8) { + refSpectrum[line*fft_size + col] /= originalRangeFilter[col]; + secSpectrum[line*fft_size + col] /= originalRangeFilter[col]; + } } } refWindowSignal.inverse(refSpectrum, refSlc); diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index c8d90fbbb..55e547a71 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -305,6 +305,8 @@ constructRangeCommonbandKaiserFilter(const double subBandCenterFrequency, std::valarray>& filter1D) { + if (filter1D.size() <= 0) filter1D.resize(fft_size); + isce3::signal::Signal signal; signal.forwardRangeFFT(filter1D, filter1D, fft_size, 1); @@ -318,7 +320,16 @@ constructRangeCommonbandKaiserFilter(const double subBandCenterFrequency, // Zero padding the filter on sides const int sizeOfKaiser = shiftedKaiser.size(); const int startInd = (fft_size - sizeOfKaiser) / 2; - const std::complex maxVal = std::abs(shiftedKaiser).max(); + + // Determine the maximum absolute value to normalize the filter + auto maxVal = std::accumulate (std::begin(shiftedKaiser), std::end(shiftedKaiser), *std::begin(shiftedKaiser), + [](const std::complex& a ,const std::complex& b) + { + auto abs_a = std::abs(a); + auto abs_b = std::abs(b); + return std::max(abs_a, abs_b); + } + ); if (startInd <= sizeOfKaiser) { std::cout << "FFT size is less than the window size\n"; diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index fd7a6cd77..cfc122a5a 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -11,6 +11,8 @@ #include #include +#include +#include #include #include From f27fe58756633a8dd60322cf17bddc02b7623d25 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 21 Nov 2023 23:39:24 +0000 Subject: [PATCH 036/106] debug range common band filter --- cxx/isce3/signal/Crossmul.cpp | 29 +++++++++++++++++++------- cxx/isce3/signal/Filter.cpp | 39 +++++++++++++++++++---------------- cxx/isce3/signal/Filter.h | 4 ++-- 3 files changed, 44 insertions(+), 28 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 77b001bc6..e7f434e7d 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -372,8 +372,8 @@ crossmul(isce3::io::Raster& refSlcRaster, std::valarray> secAzimuthSpectrum; // retrieve the original filter to revert the range windowing effects - std::valarray> originalRangeFilter(std::complex(1.0, 0.0), - fft_size); + std::valarray> originalRangeFilter; + if (_doCommonAzimuthBandFilter) { // Allocate storage for azimuth spectrum refAzimuthSpectrum.resize(spectrumSize); @@ -387,12 +387,21 @@ crossmul(isce3::io::Raster& refSlcRaster, // Compute the range frequency for each pixel fftfreq(1.0/_rangeSamplingFrequency, rangeFrequencies); - // For NISAR, build the Kaiser window to + // For NISAR, use a standard Kaiser window in frequency domain to // compensate the windowing effects in range direction - // TODO: this function is sensor dependent! - rangeFilter.constructRangeCommonbandKaiserFilter(0.0, _rangeBandwidth, - _rangeSamplingFrequency, - fft_size, 1.6, originalRangeFilter); + // TODO: This function is sensor dependent + // TODO: Need to confirm with Brian about the implementation + // rangeFilter.constructRangeCommonbandKaiserFilter(0.0, _rangeSamplingFrequency, + // _rangeSamplingFrequency, + // fft_size, 1.6, originalRangeFilter); + originalRangeFilter.resize(fft_size); + std::valarray subBandCenterFrequencies{0.0}; + std::valarray subBandBandwidths{_rangeSamplingFrequency}; + rangeFilter.constructRangeBandpassKaiser(subBandCenterFrequencies, + subBandBandwidths, + 1.0/_rangeSamplingFrequency, + fft_size, rangeFrequencies, 1.6, + originalRangeFilter); // Construct the FFTW plan for both geometryIfgram and its conjugation geometryIfgramSignal.forwardRangeFFT(geometryIfgram, refSpectrum, @@ -436,6 +445,9 @@ crossmul(isce3::io::Raster& refSlcRaster, secSlc = 0; ifgramUpsampled = 0; ifgram = 0; + geometryIfgramConj = 0; + geometryIfgram = 0; + rngOffset = 0; // get a block of reference and secondary SLC data // and a block of range offsets @@ -485,12 +497,13 @@ crossmul(isce3::io::Raster& refSlcRaster, geometryIfgramConj[line*fft_size + col] = std::conj(geometryIfgram[line*fft_size + col]); // revert the original windowing effects along the slant range direction - if (std::abs(originalRangeFilter[col]) > 1e-8) { + if (originalRangeFilter.size() > 0 && std::abs(originalRangeFilter[col]) > 1e-8) { refSpectrum[line*fft_size + col] /= originalRangeFilter[col]; secSpectrum[line*fft_size + col] /= originalRangeFilter[col]; } } } + refWindowSignal.inverse(refSpectrum, refSlc); secWindowSignal.inverse(secSpectrum, secSlc); diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 55e547a71..9c35f60a7 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -183,9 +183,10 @@ isce3::signal::Filter::constructRangeCommonbandFilter(const double rangeSampl } //construct a block of the filter + const std::complex norm(fft_size, fft_size); for (size_t line = 0; line < nrows; line++ ){ for (size_t col = 0; col < fft_size; col++ ){ - _filter[line*fft_size+col] = _filter1D[col]; + _filter[line*fft_size+col] = _filter1D[col] / norm; } } } @@ -311,27 +312,13 @@ constructRangeCommonbandKaiserFilter(const double subBandCenterFrequency, signal.forwardRangeFFT(filter1D, filter1D, fft_size, 1); std::valarray> kaiser; - std::valarray> shiftedKaiser; _design_shaped_lowpass_filter(subBandBandwidth, rangeSamplingFrequency, beta, kaiser); - // Turn into bandpass filter - _lowpass2bandpass(kaiser, subBandCenterFrequency, shiftedKaiser); - // Zero padding the filter on sides - const int sizeOfKaiser = shiftedKaiser.size(); + const int sizeOfKaiser = kaiser.size(); const int startInd = (fft_size - sizeOfKaiser) / 2; - // Determine the maximum absolute value to normalize the filter - auto maxVal = std::accumulate (std::begin(shiftedKaiser), std::end(shiftedKaiser), *std::begin(shiftedKaiser), - [](const std::complex& a ,const std::complex& b) - { - auto abs_a = std::abs(a); - auto abs_b = std::abs(b); - return std::max(abs_a, abs_b); - } - ); - - if (startInd <= sizeOfKaiser) { + if (startInd <= 0) { std::cout << "FFT size is less than the window size\n"; throw isce3::except::InvalidArgument(ISCE_SRCINFO(), "FFT size is less than the window size"); @@ -339,10 +326,26 @@ constructRangeCommonbandKaiserFilter(const double subBandCenterFrequency, // Zero padding the filter for (size_t ind = startInd; ind < startInd + sizeOfKaiser; ind ++) { - filter1D[ind] = shiftedKaiser[ind - startInd] / maxVal; + filter1D[ind] = kaiser[ind - startInd]; } + // Transform to frequency domain signal.forward(filter1D, filter1D); + + // Absolute value + filter1D = std::abs(filter1D); + + // Determine the maximum absolute value to normalize the filter + auto maxVal = std::accumulate (std::begin(filter1D), std::end(filter1D), *std::begin(filter1D), + [](const std::complex& a ,const std::complex& b) + { + auto abs_a = std::abs(a); + auto abs_b = std::abs(b); + return std::max(abs_a, abs_b); + } + ); + + filter1D /= maxVal; } /** diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index cfc122a5a..2652bc733 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -9,10 +9,10 @@ #include "forward.h" -#include -#include #include +#include #include +#include #include #include From 54fde5e6d68ab0e79aab898d73b05e89d31788e1 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 28 Nov 2023 00:03:44 +0000 Subject: [PATCH 037/106] fix the range kaiser filter --- cxx/isce3/signal/Filter.cpp | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 9c35f60a7..dd6eba915 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -314,38 +314,24 @@ constructRangeCommonbandKaiserFilter(const double subBandCenterFrequency, std::valarray> kaiser; _design_shaped_lowpass_filter(subBandBandwidth, rangeSamplingFrequency, beta, kaiser); - // Zero padding the filter on sides const int sizeOfKaiser = kaiser.size(); - const int startInd = (fft_size - sizeOfKaiser) / 2; - - if (startInd <= 0) { + const int halfSizeOfKaiser = (sizeOfKaiser - 1)/2; + if (fft_size < sizeOfKaiser) { std::cout << "FFT size is less than the window size\n"; throw isce3::except::InvalidArgument(ISCE_SRCINFO(), "FFT size is less than the window size"); } - // Zero padding the filter - for (size_t ind = startInd; ind < startInd + sizeOfKaiser; ind ++) { - filter1D[ind] = kaiser[ind - startInd]; + // Zero padding the filter on sides + for (size_t ind = halfSizeOfKaiser; ind < sizeOfKaiser; ind ++) { + filter1D[ind - halfSizeOfKaiser] = kaiser[ind]; + } + for (size_t ind = 0; ind < halfSizeOfKaiser; ind ++) { + filter1D[fft_size - halfSizeOfKaiser + ind] = kaiser[ind]; } // Transform to frequency domain signal.forward(filter1D, filter1D); - - // Absolute value - filter1D = std::abs(filter1D); - - // Determine the maximum absolute value to normalize the filter - auto maxVal = std::accumulate (std::begin(filter1D), std::end(filter1D), *std::begin(filter1D), - [](const std::complex& a ,const std::complex& b) - { - auto abs_a = std::abs(a); - auto abs_b = std::abs(b); - return std::max(abs_a, abs_b); - } - ); - - filter1D /= maxVal; } /** From ee9e3cde8f615be82e96066e798a6d50d22a0bd7 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 28 Nov 2023 01:12:53 +0000 Subject: [PATCH 038/106] change the LUT1d to 2d --- cxx/isce3/signal/Crossmul.cpp | 6 +--- cxx/isce3/signal/Crossmul.h | 18 +++++----- cxx/isce3/signal/Crossmul.icc | 2 +- cxx/isce3/signal/Filter.cpp | 34 +++++++++---------- cxx/isce3/signal/Filter.h | 15 ++++---- .../pybind_isce3/signal/Crossmul.cpp | 4 +-- tests/cxx/isce3/signal/crossmul.cpp | 10 +++--- tests/cxx/isce3/signal/filter.cpp | 2 +- 8 files changed, 45 insertions(+), 46 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index e7f434e7d..64b125ec5 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -390,10 +390,6 @@ crossmul(isce3::io::Raster& refSlcRaster, // For NISAR, use a standard Kaiser window in frequency domain to // compensate the windowing effects in range direction // TODO: This function is sensor dependent - // TODO: Need to confirm with Brian about the implementation - // rangeFilter.constructRangeCommonbandKaiserFilter(0.0, _rangeSamplingFrequency, - // _rangeSamplingFrequency, - // fft_size, 1.6, originalRangeFilter); originalRangeFilter.resize(fft_size); std::valarray subBandCenterFrequencies{0.0}; std::valarray subBandBandwidths{_rangeSamplingFrequency}; @@ -497,7 +493,7 @@ crossmul(isce3::io::Raster& refSlcRaster, geometryIfgramConj[line*fft_size + col] = std::conj(geometryIfgram[line*fft_size + col]); // revert the original windowing effects along the slant range direction - if (originalRangeFilter.size() > 0 && std::abs(originalRangeFilter[col]) > 1e-8) { + if (originalRangeFilter.size() > 0) { refSpectrum[line*fft_size + col] /= originalRangeFilter[col]; secSpectrum[line*fft_size + col] /= originalRangeFilter[col]; } diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index f9b9557cf..3f87621cf 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -4,6 +4,8 @@ #include #include +#include +#include #include /** \brief Intereferogram generation by cross-multiplication of reference and secondary SLCs. @@ -34,20 +36,20 @@ class isce3::signal::Crossmul { isce3::io::Raster* rngOffsetRaster = nullptr); /** Set doppler LUTs for reference and secondary SLCs*/ - inline void doppler(isce3::core::LUT1d, - isce3::core::LUT1d); + inline void doppler(isce3::core::LUT2d, + isce3::core::LUT2d); /** Set dopplers LUT for reference SLC */ - inline void refDoppler(isce3::core::LUT1d refDopp) { _refDoppler = refDopp; } + inline void refDoppler(isce3::core::LUT2d refDopp) { _refDoppler = refDopp; } /** Get doppler LUT for reference SLC */ - inline const isce3::core::LUT1d & refDoppler() const { return _refDoppler; } + inline const isce3::core::LUT2d & refDoppler() const { return _refDoppler; } /** Set dopplers LUT for secondary SLC */ - inline void secDoppler(isce3::core::LUT1d secDopp) { _secDoppler = secDopp; } + inline void secDoppler(isce3::core::LUT2d secDopp) { _secDoppler = secDopp; } /** Get doppler LUT for secondary SLC */ - inline const isce3::core::LUT1d & secDoppler() const { return _secDoppler; } + inline const isce3::core::LUT2d & secDoppler() const { return _secDoppler; } /** Set range pixel spacing, in meters */ inline void rangePixelSpacing(double rgPxlSpacing) { _rangePixelSpacing = rgPxlSpacing; } @@ -190,10 +192,10 @@ class isce3::signal::Crossmul { private: //Doppler LUT for the refernce SLC - isce3::core::LUT1d _refDoppler; + isce3::core::LUT2d _refDoppler; //Doppler LUT for the secondary SLC - isce3::core::LUT1d _secDoppler; + isce3::core::LUT2d _secDoppler; // range pixel spacing in meters double _rangePixelSpacing; diff --git a/cxx/isce3/signal/Crossmul.icc b/cxx/isce3/signal/Crossmul.icc index 1465d7cff..e38aad257 100644 --- a/cxx/isce3/signal/Crossmul.icc +++ b/cxx/isce3/signal/Crossmul.icc @@ -17,7 +17,7 @@ * @param[in] secSlcDoppler 2D Doppler polynomial for secondary SLC */ void isce3::signal::Crossmul:: -doppler(isce3::core::LUT1d refSlcDoppler, isce3::core::LUT1d secSlcDoppler) +doppler(isce3::core::LUT2d refSlcDoppler, isce3::core::LUT2d secSlcDoppler) { _refDoppler = refSlcDoppler; diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index dd6eba915..c14a28a6f 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -179,7 +179,7 @@ isce3::signal::Filter::constructRangeCommonbandFilter(const double rangeSampl windowParameter, _filter1D); } else { - std::cout << filterType << " filter has not been implemented" << std::endl; + std::cout << filterType << "filter has not been implemented" << std::endl; } //construct a block of the filter @@ -401,8 +401,8 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, } /** -* @param[in] refDoppler Doppler LUT1d of the reference SLC -* @param[in] secDoppler Doppler LUT1d of the secondary SLC +* @param[in] refDoppler Doppler LUT2d of the reference SLC +* @param[in] secDoppler Doppler LUT2d of the secondary SLC * @param[in] rangeOffsets Range pixel offsets between secondary and reference SLC (i.e., secondary - reference) * @param[in] bandwidth common bandwidth in azimuth * @param[in] prf pulse repetition frequency @@ -415,8 +415,8 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, template double isce3::signal::Filter:: -constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, - const isce3::core::LUT1d & secDoppler, +constructAzimuthCommonbandFilter(const isce3::core::LUT2d & refDoppler, + const isce3::core::LUT2d & secDoppler, std::valarray &rangeOffsets, double bandwidth, double prf, @@ -451,8 +451,8 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, } /** -* @param[in] refDoppler Doppler LUT1d of the reference SLC -* @param[in] secDoppler Doppler LUT1d of the secondary SLC +* @param[in] refDoppler Doppler LUT2d of the reference SLC +* @param[in] secDoppler Doppler LUT2d of the secondary SLC * @param[in] rangeOffsets Range pixel offsets between secondary and reference SLC (i.e., secondary - reference) * @param[in] bandwidth common bandwidth in azimuth * @param[in] prf pulse repetition frequency @@ -465,8 +465,8 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, template double isce3::signal::Filter:: -constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDoppler, - const isce3::core::LUT1d & secDoppler, +constructAzimuthCommonbandCosineFilter(const isce3::core::LUT2d & refDoppler, + const isce3::core::LUT2d & secDoppler, std::valarray &rangeOffsets, double bandwidth, double prf, @@ -500,8 +500,8 @@ constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDop // I think we need the range offsets here to restore the fDC // for the secondary doppler since it is the resampled RSLC // middle frequency for the reference SLC - double refFreq = refDoppler.eval(j); - double secFreq = secDoppler.eval(j + rangeOffsets[j]); + double refFreq = refDoppler.eval(0,j); + double secFreq = secDoppler.eval(0, j + rangeOffsets[j]); double fmid = 0.5 * (refFreq + secFreq); double fshift = std::abs(refFreq - secFreq); @@ -551,8 +551,8 @@ constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDop } /** -* @param[in] refDoppler Doppler LUT1d of the reference SLC -* @param[in] secDoppler Doppler LUT1d of the secondary SLC +* @param[in] refDoppler Doppler LUT2d of the reference SLC +* @param[in] secDoppler Doppler LUT2d of the secondary SLC * @param[in] rangeOffsets Range pixel offsets between secondary and reference SLC (i.e., secondary - reference) * @param[in] bandwidth common bandwidth in azimuth * @param[in] prf pulse repetition frequency @@ -565,8 +565,8 @@ constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDop template double isce3::signal::Filter:: -constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDoppler, - const isce3::core::LUT1d & secDoppler, +constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT2d & refDoppler, + const isce3::core::LUT2d & secDoppler, std::valarray &rangeOffsets, double bandwidth, double prf, @@ -593,8 +593,8 @@ constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDop // Compute center frequency of common band // the range offsets here are to restore the fDC // for the secondary doppler since it has been resampled - double refFreq = refDoppler.eval(j); - double secFreq = secDoppler.eval(j + rangeOffsets[j]); + double refFreq = refDoppler.eval(0.0,j); + double secFreq = secDoppler.eval(0.0,j + rangeOffsets[j]); double fmid = 0.5 * (refFreq + secFreq); double fshift = std::abs(refFreq - secFreq); diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index 2652bc733..bebf47121 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -17,6 +17,9 @@ #include #include #include +#include +#include + #include #include #include "Signal.h" @@ -111,8 +114,8 @@ class isce3::signal::Filter { std::valarray>& filter1D); /** Construct azimuth common band filter*/ - double constructAzimuthCommonbandFilter(const isce3::core::LUT1d & refDoppler, - const isce3::core::LUT1d & secDoppler, + double constructAzimuthCommonbandFilter(const isce3::core::LUT2d & refDoppler, + const isce3::core::LUT2d & secDoppler, std::valarray &rangeOffsets, double bandwidth, double prf, @@ -124,8 +127,8 @@ class isce3::signal::Filter { std::string filterType); /** Construct azimuth common band cosine filter with the doppler centroid compensation*/ - double constructAzimuthCommonbandCosineFilter(const isce3::core::LUT1d & refDoppler, - const isce3::core::LUT1d & secDoppler, + double constructAzimuthCommonbandCosineFilter(const isce3::core::LUT2d & refDoppler, + const isce3::core::LUT2d & secDoppler, std::valarray &rangeOffsets, double bandwidth, double prf, @@ -136,8 +139,8 @@ class isce3::signal::Filter { size_t nrows); /** Construct azimuth common band kaiser filter with the doppler centroid compensation*/ - double constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT1d & refDoppler, - const isce3::core::LUT1d & secDoppler, + double constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT2d & refDoppler, + const isce3::core::LUT2d & secDoppler, std::valarray &rangeOffsets, double bandwidth, double prf, diff --git a/python/extensions/pybind_isce3/signal/Crossmul.cpp b/python/extensions/pybind_isce3/signal/Crossmul.cpp index af34388ef..efcca2236 100644 --- a/python/extensions/pybind_isce3/signal/Crossmul.cpp +++ b/python/extensions/pybind_isce3/signal/Crossmul.cpp @@ -51,10 +51,10 @@ void addbinding(py::class_ & pyCrossmul) py::arg("sec_doppler")) .def_property("ref_doppler", py::overload_cast<>(&Crossmul::refDoppler, py::const_), - py::overload_cast>(&Crossmul::refDoppler)) + py::overload_cast>(&Crossmul::refDoppler)) .def_property("sec_doppler", py::overload_cast<>(&Crossmul::secDoppler, py::const_), - py::overload_cast>(&Crossmul::secDoppler)) + py::overload_cast>(&Crossmul::secDoppler)) .def_property("range_pixel_spacing", py::overload_cast<>(&Crossmul::rangePixelSpacing, py::const_), py::overload_cast(&Crossmul::rangePixelSpacing)) diff --git a/tests/cxx/isce3/signal/crossmul.cpp b/tests/cxx/isce3/signal/crossmul.cpp index 83c39f608..0bfbdcd84 100644 --- a/tests/cxx/isce3/signal/crossmul.cpp +++ b/tests/cxx/isce3/signal/crossmul.cpp @@ -48,12 +48,11 @@ TEST(Crossmul, RunCrossmul) isce3::product::RadarGridProduct product(file); // get the Doppler polynomial for refernce SLC - isce3::core::LUT1d dop1 = - avgLUT2dToLUT1d(product.metadata().procInfo().dopplerCentroid('A')); + isce3::core::LUT2d dop1 = product.metadata().procInfo().dopplerCentroid('A'); // Since this test careates an interferogram between the refernce SLC and itself, // the second Doppler is the same as the first - isce3::core::LUT1d dop2 = dop1; + isce3::core::LUT2d dop2 = dop1; //instantiate the Crossmul class isce3::signal::Crossmul crsmul; @@ -123,12 +122,11 @@ TEST(Crossmul, RunCrossmulMLook) isce3::product::RadarGridProduct product(file); // get the Doppler polynomial for refernce SLC - isce3::core::LUT1d dop1 = - avgLUT2dToLUT1d(product.metadata().procInfo().dopplerCentroid('A')); + isce3::core::LUT2d dop1 = product.metadata().procInfo().dopplerCentroid('A'); // Since this test careates an interferogram between the refernce SLC and itself, // the second Doppler is the same as the first - isce3::core::LUT1d dop2 = dop1; + isce3::core::LUT2d dop2 = dop1; //instantiate the Crossmul class isce3::signal::Crossmul crsmul; diff --git a/tests/cxx/isce3/signal/filter.cpp b/tests/cxx/isce3/signal/filter.cpp index 5e592810b..1a2ee61f4 100644 --- a/tests/cxx/isce3/signal/filter.cpp +++ b/tests/cxx/isce3/signal/filter.cpp @@ -38,7 +38,7 @@ TEST(Filter, constructAzimuthCommonbandFilter) const isce3::product::Swath & swath = product.swath('A'); // Get the Doppler polynomial and use it for both refernce and secondary SLCs - auto dop1 = isce3::core::avgLUT2dToLUT1d(product.metadata().procInfo().dopplerCentroid('A')); + auto dop1 = product.metadata().procInfo().dopplerCentroid('A'); auto dop2 = dop1; // get pulase repetition frequency (prf) From b1ec2180466e85949f0e6c14a7a9dd136dac2732 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 28 Nov 2023 20:02:34 +0000 Subject: [PATCH 039/106] change the doppler centroid from 1d to 2d --- cxx/isce3/cuda/signal/gpuCrossMul.cu | 4 ++-- cxx/isce3/cuda/signal/gpuCrossMul.h | 19 +++++++++++-------- .../pybind_isce3/cuda/signal/Crossmul.cpp | 4 ++-- python/packages/nisar/workflows/crossmul.py | 7 +++---- tests/cxx/isce3/cuda/signal/gpuCrossMul.cpp | 12 ++++++------ 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/cxx/isce3/cuda/signal/gpuCrossMul.cu b/cxx/isce3/cuda/signal/gpuCrossMul.cu index 0d1470275..82dc0bf4a 100644 --- a/cxx/isce3/cuda/signal/gpuCrossMul.cu +++ b/cxx/isce3/cuda/signal/gpuCrossMul.cu @@ -147,8 +147,8 @@ azimuthLooks(int azLks) { } void isce3::cuda::signal::gpuCrossmul:: -doppler(isce3::core::LUT1d refDoppler, - isce3::core::LUT1d secDoppler) +doppler(isce3::core::LUT2d refDoppler, + isce3::core::LUT2d secDoppler) { _refDoppler = refDoppler; _secDoppler = secDoppler; diff --git a/cxx/isce3/cuda/signal/gpuCrossMul.h b/cxx/isce3/cuda/signal/gpuCrossMul.h index f5354eeda..82422ef43 100644 --- a/cxx/isce3/cuda/signal/gpuCrossMul.h +++ b/cxx/isce3/cuda/signal/gpuCrossMul.h @@ -2,9 +2,12 @@ #include "forward.h" #include // Raster +#include #include #include +#include + #include class isce3::cuda::signal::gpuCrossmul { @@ -30,20 +33,20 @@ class isce3::cuda::signal::gpuCrossmul { isce3::io::Raster* rngOffsetRaster = nullptr) const; /** Set doppler LUTs for reference and secondary SLCs*/ - void doppler(isce3::core::LUT1d refDoppler, - isce3::core::LUT1d secDoppler); + void doppler(isce3::core::LUT2d refDoppler, + isce3::core::LUT2d secDoppler); /** Set reference doppler */ - inline void refDoppler(isce3::core::LUT1d refDopp) {_refDoppler = refDopp;}; + inline void refDoppler(isce3::core::LUT2d refDopp) {_refDoppler = refDopp;}; /** Get reference doppler */ - inline const isce3::core::LUT1d & refDoppler() const {return _refDoppler;}; + inline const isce3::core::LUT2d & refDoppler() const {return _refDoppler;}; /** Set secondary doppler */ - inline void secDoppler(isce3::core::LUT1d secDopp) {_secDoppler = secDopp;}; + inline void secDoppler(isce3::core::LUT2d secDopp) {_secDoppler = secDopp;}; /** Get secondary doppler */ - inline const isce3::core::LUT1d & secDoppler() const {return _secDoppler;}; + inline const isce3::core::LUT2d & secDoppler() const {return _secDoppler;}; /** Set range pixel spacing */ inline void rangePixelSpacing(double rngPxl) {_rangePixelSpacing = rngPxl;}; @@ -86,10 +89,10 @@ class isce3::cuda::signal::gpuCrossmul { private: //Doppler LUT for the refernce SLC - isce3::core::LUT1d _refDoppler; + isce3::core::LUT2d _refDoppler; //Doppler LUT for the secondary SLC - isce3::core::LUT1d _secDoppler; + isce3::core::LUT2d _secDoppler; // range pixel spacing double _rangePixelSpacing; diff --git a/python/extensions/pybind_isce3/cuda/signal/Crossmul.cpp b/python/extensions/pybind_isce3/cuda/signal/Crossmul.cpp index 3aaef0c86..96211cc91 100644 --- a/python/extensions/pybind_isce3/cuda/signal/Crossmul.cpp +++ b/python/extensions/pybind_isce3/cuda/signal/Crossmul.cpp @@ -51,10 +51,10 @@ void addbinding(py::class_ & pyCrossmul) py::arg("sec_doppler")) .def_property("ref_doppler", py::overload_cast<>(&gpuCrossmul::refDoppler, py::const_), - py::overload_cast>(&gpuCrossmul::refDoppler)) + py::overload_cast>(&gpuCrossmul::refDoppler)) .def_property("sec_doppler", py::overload_cast<>(&gpuCrossmul::secDoppler, py::const_), - py::overload_cast>(&gpuCrossmul::secDoppler)) + py::overload_cast>(&gpuCrossmul::secDoppler)) .def_property("range_pixel_spacing", py::overload_cast<>(&gpuCrossmul::rangePixelSpacing, py::const_), py::overload_cast(&gpuCrossmul::rangePixelSpacing)) diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index 9c313db38..298158d54 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -102,10 +102,9 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', crossmul_dir = scratch_path / f'crossmul/freq{freq}' crossmul_dir.mkdir(parents=True, exist_ok=True) # get 2d doppler, discard azimuth dependency, and set crossmul dopplers - ref_dopp = isce3.core.avg_lut2d_to_lut1d( - ref_slc.getDopplerCentroid(frequency=freq)) - sec_dopp = isce3.core.avg_lut2d_to_lut1d( - sec_slc.getDopplerCentroid(frequency=freq)) + ref_dopp = ref_slc.getDopplerCentroid(frequency=freq) + sec_dopp = sec_slc.getDopplerCentroid(frequency=freq) + crossmul.set_dopplers(ref_dopp, sec_dopp) freq_group_path = f'{RIFGGroupsPaths().SwathsPath}/frequency{freq}' diff --git a/tests/cxx/isce3/cuda/signal/gpuCrossMul.cpp b/tests/cxx/isce3/cuda/signal/gpuCrossMul.cpp index 00df88c89..ae596ad36 100644 --- a/tests/cxx/isce3/cuda/signal/gpuCrossMul.cpp +++ b/tests/cxx/isce3/cuda/signal/gpuCrossMul.cpp @@ -49,12 +49,12 @@ TEST(gpuCrossmul, Crossmul) isce3::product::RadarGridProduct product(file); // get the Doppler polynomial for refernce SLC - const isce3::core::LUT1d dop1 = - avgLUT2dToLUT1d(product.metadata().procInfo().dopplerCentroid('A')); + const isce3::core::LUT2d dop1 = + product.metadata().procInfo().dopplerCentroid('A'); // Since this test careates an interferogram between the refernce SLC and itself, // the second Doppler is the same as the first - isce3::core::LUT1d dop2 = dop1; + isce3::core::LUT2d dop2 = dop1; //instantiate the Crossmul class isce3::cuda::signal::gpuCrossmul crsmul; @@ -125,12 +125,12 @@ TEST(gpuCrossmul, MultilookCrossmul) isce3::product::RadarGridProduct product(file); // get the Doppler polynomial for refernce SLC - isce3::core::LUT1d dop1 = - avgLUT2dToLUT1d(product.metadata().procInfo().dopplerCentroid('A')); + isce3::core::LUT2d dop1 = + product.metadata().procInfo().dopplerCentroid('A'); // Since this test careates an interferogram between the refernce SLC and itself, // the second Doppler is the same as the first - isce3::core::LUT1d dop2 = dop1; + isce3::core::LUT2d dop2 = dop1; //instantiate the Crossmul class isce3::cuda::signal::gpuCrossmul crsmul; From 65d4d512a5eab43e41446559820b3b41d1142291 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 28 Nov 2023 23:37:42 +0000 Subject: [PATCH 040/106] compute the azimuth doppler centroids for reference and secodnary --- cxx/isce3/cuda/signal/gpuCrossMul.cu | 3 +- cxx/isce3/cuda/signal/gpuCrossMul.h | 3 +- cxx/isce3/signal/Crossmul.cpp | 67 ++++++++++++++++++- cxx/isce3/signal/Crossmul.h | 13 +++- .../pybind_isce3/cuda/signal/Crossmul.cpp | 6 +- .../pybind_isce3/signal/Crossmul.cpp | 6 +- python/packages/nisar/workflows/crossmul.py | 12 +++- 7 files changed, 98 insertions(+), 12 deletions(-) diff --git a/cxx/isce3/cuda/signal/gpuCrossMul.cu b/cxx/isce3/cuda/signal/gpuCrossMul.cu index 82dc0bf4a..df2a17679 100644 --- a/cxx/isce3/cuda/signal/gpuCrossMul.cu +++ b/cxx/isce3/cuda/signal/gpuCrossMul.cu @@ -212,7 +212,8 @@ crossmul(isce3::io::Raster& refSlcRaster, isce3::io::Raster& secSlcRaster, isce3::io::Raster& ifgRaster, isce3::io::Raster& coherenceRaster, - isce3::io::Raster* rngOffsetRaster) const + isce3::io::Raster* rngOffsetRaster, + isce3::io::Raster* aziOffsetRaster) const { // set flatten flag based range offset raster ptr value bool flatten = rngOffsetRaster ? true : false; diff --git a/cxx/isce3/cuda/signal/gpuCrossMul.h b/cxx/isce3/cuda/signal/gpuCrossMul.h index 82422ef43..7059e136e 100644 --- a/cxx/isce3/cuda/signal/gpuCrossMul.h +++ b/cxx/isce3/cuda/signal/gpuCrossMul.h @@ -30,7 +30,8 @@ class isce3::cuda::signal::gpuCrossmul { isce3::io::Raster& secSlcRaster, isce3::io::Raster& ifgRaster, isce3::io::Raster& coherenceRaster, - isce3::io::Raster* rngOffsetRaster = nullptr) const; + isce3::io::Raster* rngOffsetRaster = nullptr, + isce3::io::Raster* aziOffsetRaster = nullptr) const; /** Set doppler LUTs for reference and secondary SLCs*/ void doppler(isce3::core::LUT2d refDoppler, diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 64b125ec5..2ea4e3b7a 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -159,12 +159,62 @@ rangeCommonBandFilter(std::valarray> &refSlc, return (_rangeBandwidth - frequencyShift); } +/** +* @param[in] refDoppler 2d LUT doppler centroid frequency for reference +* @param[in] secDoppler 2d LUT doppler centroid frequency for secondary +* @param[in] rngOffsetRaster range offset product pointer +* @param[out] refDopplerCentroids blockLength number of rows +* @param[out] secDopplerCentroids blockLength number of rows +*/ +void +isce3::signal::Crossmul::_compute_DoppCentroids(const isce3::core::LUT2d & refDoppler, + const isce3::core::LUT2d & secDoppler, + isce3::io::Raster* rngOffsetRaster, + isce3::io::Raster* aziOffsetRaster, + std::valarray &refDopplerCentroids, + std::valarray &secDopplerCentroids) +{ + const size_t nrows = rngOffsetRaster->width(); + const size_t ncols = rngOffsetRaster->length(); + + if (refDopplerCentroids.size() <= 0) { + refDopplerCentroids.resize(ncols); + refDopplerCentroids = 0.0; + } + if (secDopplerCentroids.size() <= 0) { + secDopplerCentroids.resize(ncols); + secDopplerCentroids = 0.0; + } + + std::valarray rangeOffsets(ncols); + std::valarray azimuthOffsets(ncols); + + // Compute the doppler centroids for the reference and secondary images + for (size_t row = 0; row < nrows; row++) { + rngOffsetRaster->getLine(rangeOffsets, row); + aziOffsetRaster->getLine(azimuthOffsets, row); + + // TODO: Add OpenMP here? + for (size_t col = 0; col < ncols; col++) { + refDopplerCentroids[col] += refDoppler.eval(double(row), double(col)); + secDopplerCentroids[col] += secDoppler.eval(double(row) + azimuthOffsets[col], + double(col) + rangeOffsets[col]); + } + } + + // Using the avergae doppler centroid for each column to avoid the artifacts when + // process block by block + refDopplerCentroids /= nrows; + secDopplerCentroids /= nrows; +} + void isce3::signal::Crossmul:: crossmul(isce3::io::Raster& refSlcRaster, isce3::io::Raster& secSlcRaster, isce3::io::Raster& ifgRaster, isce3::io::Raster& coherenceRaster, - isce3::io::Raster* rngOffsetRaster) + isce3::io::Raster* rngOffsetRaster, + isce3::io::Raster* aziOffsetRaster) { // setting local lines per block to avoid modifying class member size_t linesPerBlock = _linesPerBlock; @@ -374,10 +424,25 @@ crossmul(isce3::io::Raster& refSlcRaster, // retrieve the original filter to revert the range windowing effects std::valarray> originalRangeFilter; + // Declare valarray for range and azimuth doppler centroids used by filter + std::valarray refDoppCentroids; + std::valarray secDoppCentroids; + if (_doCommonAzimuthBandFilter) { // Allocate storage for azimuth spectrum refAzimuthSpectrum.resize(spectrumSize); secAzimuthSpectrum.resize(spectrumSize); + + // Compute the mean doppler centroid of each slant range for + // the reference and secondary images for each slant range + refDoppCentroids.resize(fft_size); refDoppCentroids = 0.0; + secDoppCentroids.resize(fft_size); secDoppCentroids = 0.0; + + _compute_DoppCentroids(_refDoppler, _secDoppler, + rngOffsetRaster, + aziOffsetRaster, + refDoppCentroids, + secDoppCentroids); } if (_doCommonRangeBandFilter) { diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 3f87621cf..40749147b 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -27,13 +27,15 @@ class isce3::signal::Crossmul { * \param[out] ifgRaster output interferogram raster * \param[out] coherenceRaster output coherence raster * \param[in] rngOffsetRaster optional pointer to range offset raster - * if provided, interferogram will be flattened + * \param[in] aziOffsetRaster optional pointer to azimuth offset raster + * */ void crossmul(isce3::io::Raster& refSlcRaster, isce3::io::Raster& secSlcRaster, isce3::io::Raster& ifgRaster, isce3::io::Raster& coherence, - isce3::io::Raster* rngOffsetRaster = nullptr); + isce3::io::Raster* rngOffsetRaster = nullptr, + isce3::io::Raster* aziOffsetRaster = nullptr); /** Set doppler LUTs for reference and secondary SLCs*/ inline void doppler(isce3::core::LUT2d, @@ -191,6 +193,13 @@ class isce3::signal::Crossmul { size_t ncols); private: + void _compute_DoppCentroids(const isce3::core::LUT2d & refDoppler, + const isce3::core::LUT2d & secDoppler, + isce3::io::Raster* rngOffsetRaster, + isce3::io::Raster* aziOffsetRaster, + std::valarray &refDopplerCentroids, + std::valarray &secDopplerCentroids); + //Doppler LUT for the refernce SLC isce3::core::LUT2d _refDoppler; diff --git a/python/extensions/pybind_isce3/cuda/signal/Crossmul.cpp b/python/extensions/pybind_isce3/cuda/signal/Crossmul.cpp index 96211cc91..a4242d174 100644 --- a/python/extensions/pybind_isce3/cuda/signal/Crossmul.cpp +++ b/python/extensions/pybind_isce3/cuda/signal/Crossmul.cpp @@ -30,7 +30,8 @@ void addbinding(py::class_ & pyCrossmul) py::arg("sec_slc"), py::arg("interferogram"), py::arg("coherence"), - py::arg("range_offset") = nullptr, R"( + py::arg("range_offset") = nullptr, + py::arg("azimuth_offset") = nullptr, R"( Crossmultiply reference and secondary SLCs to generate interferogram and coherence products. Parameters @@ -44,7 +45,8 @@ void addbinding(py::class_ & pyCrossmul) coherence: Raster Output coherence raster interferogram: Raster - Optional range offset raster usef for flattening + Optional range offset raster usef for flattening and common band filtering + Optional azimuth offset raster usef for azimuth common band filtering )") .def("set_dopplers", &gpuCrossmul::doppler, py::arg("ref_doppler"), diff --git a/python/extensions/pybind_isce3/signal/Crossmul.cpp b/python/extensions/pybind_isce3/signal/Crossmul.cpp index efcca2236..288056910 100644 --- a/python/extensions/pybind_isce3/signal/Crossmul.cpp +++ b/python/extensions/pybind_isce3/signal/Crossmul.cpp @@ -30,7 +30,8 @@ void addbinding(py::class_ & pyCrossmul) py::arg("sec_slc"), py::arg("interferogram"), py::arg("coherence"), - py::arg("range_offset") = nullptr, R"( + py::arg("range_offset") = nullptr, + py::arg("azimuth_offset") = nullptr, R"( Crossmultiply reference and secondary SLCs to generate interferogram and coherence products. Parameters @@ -44,7 +45,8 @@ void addbinding(py::class_ & pyCrossmul) coherence: Raster Output coherence raster interferogram: Raster - Optional range offset raster usef for flattening + Optional range offset raster usef for flattening and common band filter + Optional range offset raster usef for azimuth common band filter )") .def("set_dopplers", &Crossmul::doppler, py::arg("ref_doppler"), diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index 298158d54..cbb94b397 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -130,10 +130,14 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', # enable/disable flatten accordingly if flatten or do_common_range_band_filter or do_common_azimuth_band_filter: # set frequency dependent range offset raster - flatten_raster = isce3.io.Raster( + range_offsets_raster = isce3.io.Raster( f'{flatten_path}/geo2rdr/freq{freq}/range.off') + if do_common_azimuth_band_filter: + azimuth_offsets_raster = isce3.io.Raster( + f'{flatten_path}/geo2rdr/freq{freq}/azimuth.off') else: - flatten_raster = None + range_offsets_raster = None + azimuth_offsets_raster = None for pol in pol_list: output_dir = crossmul_dir / f'{pol}' @@ -190,7 +194,9 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', # Compute multilooked interferogram and coherence raster crossmul.crossmul(ref_slc_raster, sec_slc_raster, ifg_raster, - coh_raster, flatten_raster) + coh_raster, + range_offsets_raster, + azimuth_offsets_raster) # populate the new bandwidth along azimuth and range after the common band filter # if there is no common band filter applied, the bandwith will remain the same with From 03555c457e8eac41ffc3cfbc04a22a93e10fd114 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 28 Nov 2023 23:55:03 +0000 Subject: [PATCH 041/106] fix azimuth bugs --- cxx/isce3/signal/Crossmul.cpp | 4 ++-- cxx/isce3/signal/Filter.cpp | 40 +++++++++++++------------------ cxx/isce3/signal/Filter.h | 15 +++++------- tests/cxx/isce3/signal/filter.cpp | 11 +++++---- 4 files changed, 30 insertions(+), 40 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 2ea4e3b7a..2ee9b06ac 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -589,7 +589,7 @@ crossmul(isce3::io::Raster& refSlcRaster, std::string filterType = _windowType; // Construct azimuth common band filter for a block of data of the reference _processedAzimuthBandwidth += azimuthFilter.constructAzimuthCommonbandFilter( - _refDoppler, _secDoppler, rngOffset, + refDoppCentroids, secDoppCentroids, _azimuthBandwidth, _prf, _windowParameter, refSlc, refAzimuthSpectrum, fft_size, linesPerBlock, filterType); @@ -597,7 +597,7 @@ crossmul(isce3::io::Raster& refSlcRaster, // Construct azimuth common band filter for a block of data of the secondary azimuthFilter.constructAzimuthCommonbandFilter( - _refDoppler, _secDoppler, rngOffset, + refDoppCentroids, secDoppCentroids, _azimuthBandwidth, _prf, _windowParameter, secSlc, secAzimuthSpectrum, fft_size, linesPerBlock, filterType); diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index c14a28a6f..fe10b167b 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -401,9 +401,8 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, } /** -* @param[in] refDoppler Doppler LUT2d of the reference SLC -* @param[in] secDoppler Doppler LUT2d of the secondary SLC -* @param[in] rangeOffsets Range pixel offsets between secondary and reference SLC (i.e., secondary - reference) +* @param[in] refDoppler Doppler Centroids of the reference SLC +* @param[in] secDoppler Doppler Centroids of the secondary SLC * @param[in] bandwidth common bandwidth in azimuth * @param[in] prf pulse repetition frequency * @param[in] beta parameter for raised cosine filter (0.25) or for the kaiser filter (2.5) @@ -415,9 +414,8 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, template double isce3::signal::Filter:: -constructAzimuthCommonbandFilter(const isce3::core::LUT2d & refDoppler, - const isce3::core::LUT2d & secDoppler, - std::valarray &rangeOffsets, +constructAzimuthCommonbandFilter(const std::valarray & refDoppler, + const std::valarray & secDoppler, double bandwidth, double prf, double beta, @@ -431,7 +429,6 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT2d & refDoppler, return constructAzimuthCommonbandCosineFilter( refDoppler, secDoppler, - rangeOffsets, bandwidth, prf, beta, signal, spectrum, ncols, nrows); @@ -440,7 +437,6 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT2d & refDoppler, return constructAzimuthCommonbandKaiserFilter( refDoppler, secDoppler, - rangeOffsets, bandwidth, prf, beta, signal, spectrum, ncols, nrows); @@ -451,9 +447,8 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT2d & refDoppler, } /** -* @param[in] refDoppler Doppler LUT2d of the reference SLC -* @param[in] secDoppler Doppler LUT2d of the secondary SLC -* @param[in] rangeOffsets Range pixel offsets between secondary and reference SLC (i.e., secondary - reference) +* @param[in] refDoppler Doppler Centroids of the reference SLC +* @param[in] secDoppler Doppler Centroids of the secondary SLC * @param[in] bandwidth common bandwidth in azimuth * @param[in] prf pulse repetition frequency * @param[in] beta parameter for raised cosine filter @@ -465,9 +460,8 @@ constructAzimuthCommonbandFilter(const isce3::core::LUT2d & refDoppler, template double isce3::signal::Filter:: -constructAzimuthCommonbandCosineFilter(const isce3::core::LUT2d & refDoppler, - const isce3::core::LUT2d & secDoppler, - std::valarray &rangeOffsets, +constructAzimuthCommonbandCosineFilter(const std::valarray & refDoppler, + const std::valarray & secDoppler, double bandwidth, double prf, double beta, @@ -500,8 +494,8 @@ constructAzimuthCommonbandCosineFilter(const isce3::core::LUT2d & refDop // I think we need the range offsets here to restore the fDC // for the secondary doppler since it is the resampled RSLC // middle frequency for the reference SLC - double refFreq = refDoppler.eval(0,j); - double secFreq = secDoppler.eval(0, j + rangeOffsets[j]); + double refFreq = refDoppler[j]; + double secFreq = secDoppler[j]; double fmid = 0.5 * (refFreq + secFreq); double fshift = std::abs(refFreq - secFreq); @@ -551,9 +545,8 @@ constructAzimuthCommonbandCosineFilter(const isce3::core::LUT2d & refDop } /** -* @param[in] refDoppler Doppler LUT2d of the reference SLC -* @param[in] secDoppler Doppler LUT2d of the secondary SLC -* @param[in] rangeOffsets Range pixel offsets between secondary and reference SLC (i.e., secondary - reference) +* @param[in] refDoppler Doppler Centroids of the reference SLC +* @param[in] secDoppler Doppler Centroids of the secondary SLC * @param[in] bandwidth common bandwidth in azimuth * @param[in] prf pulse repetition frequency * @param[in] beta parameter for kaiser filter @@ -565,9 +558,8 @@ constructAzimuthCommonbandCosineFilter(const isce3::core::LUT2d & refDop template double isce3::signal::Filter:: -constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT2d & refDoppler, - const isce3::core::LUT2d & secDoppler, - std::valarray &rangeOffsets, +constructAzimuthCommonbandKaiserFilter(const std::valarray & refDoppler, + const std::valarray & secDoppler, double bandwidth, double prf, double beta, @@ -593,8 +585,8 @@ constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT2d & refDop // Compute center frequency of common band // the range offsets here are to restore the fDC // for the secondary doppler since it has been resampled - double refFreq = refDoppler.eval(0.0,j); - double secFreq = secDoppler.eval(0.0,j + rangeOffsets[j]); + double refFreq = refDoppler[j]; + double secFreq = secDoppler[j]; double fmid = 0.5 * (refFreq + secFreq); double fshift = std::abs(refFreq - secFreq); diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index bebf47121..ea443b848 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -114,9 +114,8 @@ class isce3::signal::Filter { std::valarray>& filter1D); /** Construct azimuth common band filter*/ - double constructAzimuthCommonbandFilter(const isce3::core::LUT2d & refDoppler, - const isce3::core::LUT2d & secDoppler, - std::valarray &rangeOffsets, + double constructAzimuthCommonbandFilter(const std::valarray & refDoppler, + const std::valarray & secDoppler, double bandwidth, double prf, double beta, @@ -127,9 +126,8 @@ class isce3::signal::Filter { std::string filterType); /** Construct azimuth common band cosine filter with the doppler centroid compensation*/ - double constructAzimuthCommonbandCosineFilter(const isce3::core::LUT2d & refDoppler, - const isce3::core::LUT2d & secDoppler, - std::valarray &rangeOffsets, + double constructAzimuthCommonbandCosineFilter(const std::valarray & refDoppler, + const std::valarray & secDoppler, double bandwidth, double prf, double beta, @@ -139,9 +137,8 @@ class isce3::signal::Filter { size_t nrows); /** Construct azimuth common band kaiser filter with the doppler centroid compensation*/ - double constructAzimuthCommonbandKaiserFilter(const isce3::core::LUT2d & refDoppler, - const isce3::core::LUT2d & secDoppler, - std::valarray &rangeOffsets, + double constructAzimuthCommonbandKaiserFilter(const std::valarray & refDoppler, + const std::valarray & secDoppler, double bandwidth, double prf, double beta, diff --git a/tests/cxx/isce3/signal/filter.cpp b/tests/cxx/isce3/signal/filter.cpp index 1a2ee61f4..18b6a183f 100644 --- a/tests/cxx/isce3/signal/filter.cpp +++ b/tests/cxx/isce3/signal/filter.cpp @@ -24,8 +24,6 @@ TEST(Filter, constructAzimuthCommonbandFilter) std::valarray> refSlc(ncols*blockRows); std::valarray> refSpectrum(nfft*blockRows); - std::valarray rangeOffsets(nfft*blockRows); - rangeOffsets = 0.0; // Get some metadata from an existing HDF5 file std::string h5file(TESTDATA_DIR "envisat.h5"); @@ -38,8 +36,12 @@ TEST(Filter, constructAzimuthCommonbandFilter) const isce3::product::Swath & swath = product.swath('A'); // Get the Doppler polynomial and use it for both refernce and secondary SLCs - auto dop1 = product.metadata().procInfo().dopplerCentroid('A'); - auto dop2 = dop1; + std::valarray dop1(nfft); + std::valarray dop2(nfft); + + auto dop_lut2 = product.metadata().procInfo().dopplerCentroid('A'); + dop1 = dop_lut2.eval(0,0); + dop2 = dop1; // get pulase repetition frequency (prf) double prf = swath.nominalAcquisitionPRF(); @@ -54,7 +56,6 @@ TEST(Filter, constructAzimuthCommonbandFilter) isce3::signal::Filter filter; filter.constructAzimuthCommonbandCosineFilter(dop1, dop2, - rangeOffsets, commonAzimuthBandwidth, prf, beta, From bdd63a0a4c66de9b97814ccd7e884178d19357d4 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 29 Nov 2023 02:28:56 +0000 Subject: [PATCH 042/106] add the azimuth filter --- cxx/isce3/signal/Crossmul.cpp | 21 +++++-- cxx/isce3/signal/Crossmul.h | 28 +++++++++ cxx/isce3/signal/Filter.cpp | 63 +++++++++++-------- .../pybind_isce3/signal/Crossmul.cpp | 12 ++++ python/packages/nisar/workflows/crossmul.py | 11 ++++ 5 files changed, 103 insertions(+), 32 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 2ee9b06ac..a7201f22f 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -174,8 +174,8 @@ isce3::signal::Crossmul::_compute_DoppCentroids(const isce3::core::LUT2d std::valarray &refDopplerCentroids, std::valarray &secDopplerCentroids) { - const size_t nrows = rngOffsetRaster->width(); - const size_t ncols = rngOffsetRaster->length(); + const size_t ncols = rngOffsetRaster->width(); + const size_t nrows = rngOffsetRaster->length(); if (refDopplerCentroids.size() <= 0) { refDopplerCentroids.resize(ncols); @@ -196,9 +196,19 @@ isce3::signal::Crossmul::_compute_DoppCentroids(const isce3::core::LUT2d // TODO: Add OpenMP here? for (size_t col = 0; col < ncols; col++) { - refDopplerCentroids[col] += refDoppler.eval(double(row), double(col)); - secDopplerCentroids[col] += secDoppler.eval(double(row) + azimuthOffsets[col], - double(col) + rangeOffsets[col]); + + // Convert the line/pixel to range doppler coordinates + double refX = col * rangePixelSpacing() + refStartRange(); + double refY = row / prf() + refStartAzimuthTime(); + + double secX = (col + rangeOffsets[col]) * rangePixelSpacing() + secStartRange(); + double secY = (row + azimuthOffsets[col]) / prf() + secStartAzimuthTime(); + + // Interpolate the doppler centroids + if (refDoppler.contains(refY, refX) && secDoppler.contains(secY, secX)) { + refDopplerCentroids[col] += refDoppler.eval(refY, refX); + secDopplerCentroids[col] += secDoppler.eval(secY, secX); + } } } @@ -438,6 +448,7 @@ crossmul(isce3::io::Raster& refSlcRaster, refDoppCentroids.resize(fft_size); refDoppCentroids = 0.0; secDoppCentroids.resize(fft_size); secDoppCentroids = 0.0; + std::cout << " - compute the doppler centroids\n"; _compute_DoppCentroids(_refDoppler, _secDoppler, rngOffsetRaster, aziOffsetRaster, diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 40749147b..b78891ed1 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -59,6 +59,22 @@ class isce3::signal::Crossmul { /** Get range pixel spacing, in meters */ inline double rangePixelSpacing() const { return _rangePixelSpacing; } + /** Set start range for reference and secondary, in meters */ + inline void refStartRange(double startRng) { _refStartRange = startRng; } + inline void secStartRange(double startRng) { _secStartRange = startRng; } + + /** Get start range for reference and secondary , in meters */ + inline double refStartRange() const { return _refStartRange; } + inline double secStartRange() const { return _secStartRange; } + + /** Set start azimuth time for reference and secondary, in seconds */ + inline void refStartAzimuthTime(double startAziTime) { _refStartAzimuthTime = startAziTime; } + inline void secStartAzimuthTime(double startAziTime) { _secStartAzimuthTime = startAziTime; } + + /** Get start azimuth time for reference and secondary, in seconds */ + inline double refStartAzimuthTime() const { return _refStartAzimuthTime; } + inline double secStartAzimuthTime() const { return _secStartAzimuthTime; } + /** Set Wavelength, in meters*/ inline void wavelength(double wvl) { _wavelength = wvl; } @@ -209,6 +225,18 @@ class isce3::signal::Crossmul { // range pixel spacing in meters double _rangePixelSpacing; + // reference starting range + double _refStartRange; + + // reference starting azimuth time + double _refStartAzimuthTime; + + // secondary starting range + double _secStartRange; + + // secondary starting azimuth time + double _secStartAzimuthTime; + // radar wavelength in meters double _wavelength; diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index fe10b167b..702c11427 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -569,53 +569,62 @@ constructAzimuthCommonbandKaiserFilter(const std::valarray & refDoppler, size_t nrows) { _filter.resize(ncols*nrows); - _filter = std::complex(0.0, 0.0); - // we probably need to give next power of 2 ??? + _filter = std::complex(0.0, 0.0); int fft_size = nrows; - // Construct vector of frequencies - std::valarray frequency(fft_size); - fftfreq(1.0/prf, frequency); - // bessel_i0 of beta - double bessel_i0_beta = isce3::math::bessel_i0(beta); + std::valarray> filter1D(fft_size); + isce3::signal::Signal doppSignal; + doppSignal.forwardRangeFFT(filter1D, filter1D, fft_size, 1); + double meanDopCenterFreq = 0.0; double meanDopCenterFreqShift = 0.0; + // Loop over range bins for (int j = 0; j < ncols; ++j) { - // Compute center frequency of common band - // the range offsets here are to restore the fDC - // for the secondary doppler since it has been resampled + // Compute the mean doppler center frequency double refFreq = refDoppler[j]; double secFreq = secDoppler[j]; double fmid = 0.5 * (refFreq + secFreq); double fshift = std::abs(refFreq - secFreq); - meanDopCenterFreqShift += fshift; - meanDopCenterFreq += fmid; + std::valarray> kaiser; + _design_shaped_lowpass_filter(bandwidth - fshift, prf, beta, kaiser); - // Compute the filter centered at fmid - for (size_t i = 0; i < frequency.size(); ++i) { + // Turn into the bandpass filter + _lowpass2bandpass(kaiser, fmid/prf, kaiser); - double freq = frequency[i] - fmid; + const int sizeOfKaiser = kaiser.size(); + const int halfSizeOfKaiser = (sizeOfKaiser - 1)/2; + if (fft_size < sizeOfKaiser) { + std::cout << "FFT size is less than the window size\n"; + throw isce3::except::InvalidArgument(ISCE_SRCINFO(), + "FFT size is less than the window size"); + } + // Zero padding the filter on sides + filter1D = std::complex(0.0, 0.0); + for (size_t ind = halfSizeOfKaiser; ind < sizeOfKaiser; ind ++) { + filter1D[ind - halfSizeOfKaiser] = kaiser[ind]; + } + for (size_t ind = 0; ind < halfSizeOfKaiser; ind ++) { + filter1D[fft_size - halfSizeOfKaiser + ind] = kaiser[ind]; + } - // make it circular - if (freq > prf/2.0) freq -= prf; - if (freq < -prf/2.0) freq += prf; + // Transform to frequency domain + doppSignal.forward(filter1D, filter1D); - if (std::abs(freq) > 0.5 * (bandwidth - fshift)) { - _filter[i*ncols+j] = std::complex(0.0,0.0); - } - else { - double tmp = 2.0 * freq / prf; - double kaiserCoefficient = isce3::math::bessel_i0(beta * sqrt(1.0 - tmp * tmp)); - _filter[i*ncols+j] = std::complex(kaiserCoefficient/bessel_i0_beta, 0.0); - } + meanDopCenterFreqShift += fshift; + meanDopCenterFreq += fmid; + + // Compute the filter centered at fmid + for (size_t i = 0; i < filter1D.size(); ++i) { + _filter[i*ncols+j] = filter1D[i]; } } meanDopCenterFreq /= ncols; meanDopCenterFreqShift /= ncols; + std::cout << " - mean doppler center freq (Hz):" << meanDopCenterFreq << std::endl; std::cout << " - mean doppler center freq shift (Hz):" << meanDopCenterFreqShift << std::endl; @@ -831,7 +840,7 @@ isce3::signal::Filter::_lowpass2bandpass(const std::valarray> if (shifted_kaiser_window.size() <= 0) shifted_kaiser_window.resize(kaiser_window.size()); const int n = kaiser_window.size(); for (size_t i = 0; i < n; i++) { - const double t = i - (n - 1) / 2.0; + const double t = (i - (n - 1) / 2.0); const double phase = 2.0 * M_PI * fc * t; const std::complex ramp_phase(std::cos(phase), std::sin(phase)); shifted_kaiser_window[i] = kaiser_window[i] * ramp_phase; diff --git a/python/extensions/pybind_isce3/signal/Crossmul.cpp b/python/extensions/pybind_isce3/signal/Crossmul.cpp index 288056910..8b4b7504c 100644 --- a/python/extensions/pybind_isce3/signal/Crossmul.cpp +++ b/python/extensions/pybind_isce3/signal/Crossmul.cpp @@ -81,6 +81,18 @@ void addbinding(py::class_ & pyCrossmul) .def_property("range_bandwidth", py::overload_cast<>(&Crossmul::rangeBandwidth, py::const_), py::overload_cast(&Crossmul::rangeBandwidth)) + .def_property("ref_start_range", + py::overload_cast<>(&Crossmul::refStartRange, py::const_), + py::overload_cast(&Crossmul::refStartRange)) + .def_property("ref_start_azimuth_time", + py::overload_cast<>(&Crossmul::refStartAzimuthTime, py::const_), + py::overload_cast(&Crossmul::refStartAzimuthTime)) + .def_property("sec_start_range", + py::overload_cast<>(&Crossmul::secStartRange, py::const_), + py::overload_cast(&Crossmul::secStartRange)) + .def_property("sec_start_azimuth_time", + py::overload_cast<>(&Crossmul::secStartAzimuthTime, py::const_), + py::overload_cast(&Crossmul::secStartAzimuthTime)) .def_property("azimuth_bandwidth", py::overload_cast<>(&Crossmul::azimuthBandwidth, py::const_), py::overload_cast(&Crossmul::azimuthBandwidth)) diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index cbb94b397..c1877f030 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -117,6 +117,9 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', # CPU version # TODO: Add parameters to GPU implementation if not use_gpu: + + sec_rdr_grid = sec_slc.getRadarGrid(freq) + # range sampling rate and bandwidth crossmul.range_sampling_frequency = \ 1.0 / (crossmul.range_pixel_spacing*2.0/isce3.core.speed_of_light) @@ -127,6 +130,12 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', ref_slc.getSwathMetadata(freq).processed_azimuth_bandwidth crossmul.prf = rdr_grid.prf + # start range and azimuth time for reference and secondary images + crossmul.ref_start_range = rdr_grid.starting_range + crossmul.sec_start_range = sec_rdr_grid.starting_range + crossmul.ref_start_azimuth_time = rdr_grid.sensing_start + crossmul.sec_start_azimuth_time = sec_rdr_grid.sensing_start + # enable/disable flatten accordingly if flatten or do_common_range_band_filter or do_common_azimuth_band_filter: # set frequency dependent range offset raster @@ -135,6 +144,8 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', if do_common_azimuth_band_filter: azimuth_offsets_raster = isce3.io.Raster( f'{flatten_path}/geo2rdr/freq{freq}/azimuth.off') + else: + azimuth_offsets_raster = None else: range_offsets_raster = None azimuth_offsets_raster = None From afc1545f4eccb8ee70aa10453e7e496f2428100e Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 29 Nov 2023 21:12:18 +0000 Subject: [PATCH 043/106] determine the max kernel size --- cxx/isce3/signal/Crossmul.cpp | 74 +++++++++++++++++++++++++++++++++-- cxx/isce3/signal/Crossmul.h | 9 +++++ 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index a7201f22f..180645b13 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -159,6 +159,57 @@ rangeCommonBandFilter(std::valarray> &refSlc, return (_rangeBandwidth - frequencyShift); } +/** +* @param[in] refDopplerCentroids doppler centroid frequency for reference +* @param[in] secDopplerCentroids doppler centroid frequency for secondary +* @param[in] bandwidth bandwidth +* @param[in] prf pule repeat frequency +* @param[in] beta kaiser window parameter +* @param[in] aziFilter azimuth filter + +*/ +int +isce3::signal::Crossmul::_maximum_kernel_size(std::valarray &refDopplerCentroids, + std::valarray &secDopplerCentroids, + const double bandwidth, + const double prf, + const double beta, + isce3::signal::Filter &aziFilter, + const double stopatt, + const double transition_width) +{ + int max_kernel_size = -1; + + // Loop over columns to get the maximum kernel size + #pragma omp parallel for reduction(max:max_kernel_size) + for (size_t j = 0; j < refDopplerCentroids.size(); ++j) { + if (std::abs(refDopplerCentroids[j]) > 0 && std::abs(secDopplerCentroids[j]) > 0) { + double refFreq = refDopplerCentroids[j]; + double secFreq = secDopplerCentroids[j]; + double fshift = std::abs(refFreq - secFreq); + + // Normalized bandwdith + const double bw = (bandwidth - fshift)/ prf; + + // Transition width is specified in terms of output bandwidth, so scale to + // get width at sample rate of filter. + const double tw = transition_width * bw; + if ((bw + tw / 2.0) > 1.0) { + std::cout << "Passband + transition cannot exceed Nyquist\n"; + throw isce3::except::InvalidArgument(ISCE_SRCINFO(), + "Passband + transition cannot exceed Nyquist"); + } + + int n = 0; + double beta = 0.0; + aziFilter._kaiserord(stopatt, tw, n, beta); + if (n > max_kernel_size) max_kernel_size = n; + } + } + + return max_kernel_size; +} + /** * @param[in] refDoppler 2d LUT doppler centroid frequency for reference * @param[in] secDoppler 2d LUT doppler centroid frequency for secondary @@ -188,13 +239,15 @@ isce3::signal::Crossmul::_compute_DoppCentroids(const isce3::core::LUT2d std::valarray rangeOffsets(ncols); std::valarray azimuthOffsets(ncols); + std::valarray validNumbers(ncols); + validNumbers = 0; // Compute the doppler centroids for the reference and secondary images for (size_t row = 0; row < nrows; row++) { rngOffsetRaster->getLine(rangeOffsets, row); aziOffsetRaster->getLine(azimuthOffsets, row); - // TODO: Add OpenMP here? + #pragma omp parallel for for (size_t col = 0; col < ncols; col++) { // Convert the line/pixel to range doppler coordinates @@ -208,14 +261,20 @@ isce3::signal::Crossmul::_compute_DoppCentroids(const isce3::core::LUT2d if (refDoppler.contains(refY, refX) && secDoppler.contains(secY, secX)) { refDopplerCentroids[col] += refDoppler.eval(refY, refX); secDopplerCentroids[col] += secDoppler.eval(secY, secX); + validNumbers[col]++; } } } // Using the avergae doppler centroid for each column to avoid the artifacts when // process block by block - refDopplerCentroids /= nrows; - secDopplerCentroids /= nrows; + #pragma omp parallel for + for (size_t col = 0; col < ncols; col++) { + if (validNumbers[col] > 0) { + refDopplerCentroids[col] /= validNumbers[col]; + secDopplerCentroids[col] /= validNumbers[col]; + } + } } void isce3::signal::Crossmul:: @@ -438,6 +497,7 @@ crossmul(isce3::io::Raster& refSlcRaster, std::valarray refDoppCentroids; std::valarray secDoppCentroids; + size_t maxKernelSize = -1; if (_doCommonAzimuthBandFilter) { // Allocate storage for azimuth spectrum refAzimuthSpectrum.resize(spectrumSize); @@ -454,6 +514,14 @@ crossmul(isce3::io::Raster& refSlcRaster, aziOffsetRaster, refDoppCentroids, secDoppCentroids); + + maxKernelSize = _maximum_kernel_size(refDoppCentroids, + secDoppCentroids, + _azimuthBandwidth, + _prf, + _windowParameter, + azimuthFilter); + std::cout << " - max kernel size = " << maxKernelSize << std::endl; } if (_doCommonRangeBandFilter) { diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index b78891ed1..d6a4ada0d 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -216,6 +216,15 @@ class isce3::signal::Crossmul { std::valarray &refDopplerCentroids, std::valarray &secDopplerCentroids); + int _maximum_kernel_size(std::valarray &refDopplerCentroids, + std::valarray &secDopplerCentroids, + const double bandwidth, + const double prf, + const double beta, + isce3::signal::Filter &aziFilter, + const double stopatt = 40.0, + const double transition_width = 0.15); + //Doppler LUT for the refernce SLC isce3::core::LUT2d _refDoppler; From d7bbda85c147d6a03e143f87fc403c48c03e9400 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 30 Nov 2023 22:49:01 +0000 Subject: [PATCH 044/106] determine the overlap size --- cxx/isce3/signal/Crossmul.cpp | 95 ++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 180645b13..b27bdc586 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -285,9 +285,23 @@ crossmul(isce3::io::Raster& refSlcRaster, isce3::io::Raster* rngOffsetRaster, isce3::io::Raster* aziOffsetRaster) { + + // number of threads + size_t nthreads = omp_thread_count(); + // setting local lines per block to avoid modifying class member size_t linesPerBlock = _linesPerBlock; + //filter objects which will be used for azimuth and range common band filtering + isce3::signal::Filter azimuthFilter; + isce3::signal::Filter rangeFilter; + + //signal object for refSlc + isce3::signal::Signal refSignal(nthreads); + + //signal object for secSlc + isce3::signal::Signal secSignal(nthreads); + // check consistency of input/output raster shapes size_t nrows = refSlcRaster.length(); size_t ncols = refSlcRaster.width(); @@ -300,6 +314,42 @@ crossmul(isce3::io::Raster& refSlcRaster, throw isce3::except::LengthError(ISCE_SRCINFO(), "interferogram and coherence rasters width do not match"); + // Compute FFT size (power of 2) + size_t fft_size; + refSignal.nextPowerOfTwo(ncols, fft_size); + + if (fft_size > INT_MAX) + throw isce3::except::LengthError(ISCE_SRCINFO(), "fft_size > INT_MAX"); + if (_oversampleFactor * fft_size > INT_MAX) + throw isce3::except::LengthError(ISCE_SRCINFO(), "_oversampleFactor * fft_size > INT_MAX"); + + // Declare valarray for range and azimuth doppler centroids used by filter + std::valarray refDoppCentroids; + std::valarray secDoppCentroids; + + size_t maxKernelSize = -1; + if (_doCommonAzimuthBandFilter) { + // Compute the mean doppler centroid of each slant range for + // the reference and secondary images for each slant range + refDoppCentroids.resize(fft_size); refDoppCentroids = 0.0; + secDoppCentroids.resize(fft_size); secDoppCentroids = 0.0; + + std::cout << " - compute the doppler centroids\n"; + _compute_DoppCentroids(_refDoppler, _secDoppler, + rngOffsetRaster, + aziOffsetRaster, + refDoppCentroids, + secDoppCentroids); + + maxKernelSize = _maximum_kernel_size(refDoppCentroids, + secDoppCentroids, + _azimuthBandwidth, + _prf, + _windowParameter, + azimuthFilter); + std::cout << " - max kernel size = " << maxKernelSize << std::endl; + } + const auto output_rows = ifgRaster.length(); const auto output_cols = ifgRaster.width(); if (_multiLookEnabled) { @@ -328,13 +378,6 @@ crossmul(isce3::io::Raster& refSlcRaster, "full resolution input/output raster widths do not match"); } - size_t nthreads = omp_thread_count(); - - //signal object for refSlc - isce3::signal::Signal refSignal(nthreads); - - //signal object for secSlc - isce3::signal::Signal secSignal(nthreads); //signal object for geometryIfgram isce3::signal::Signal geometryIfgramSignal(nthreads); @@ -360,15 +403,6 @@ crossmul(isce3::io::Raster& refSlcRaster, looksObj.nrowsLooked(linesPerBlockMLooked); looksObj.ncolsLooked(ncolsMultiLooked); - // Compute FFT size (power of 2) - size_t fft_size; - refSignal.nextPowerOfTwo(ncols, fft_size); - - if (fft_size > INT_MAX) - throw isce3::except::LengthError(ISCE_SRCINFO(), "fft_size > INT_MAX"); - if (_oversampleFactor * fft_size > INT_MAX) - throw isce3::except::LengthError(ISCE_SRCINFO(), "_oversampleFactor * fft_size > INT_MAX"); - // number of blocks to process size_t nblocks = nrows / linesPerBlock; if (nblocks == 0) { @@ -479,10 +513,6 @@ crossmul(isce3::io::Raster& refSlcRaster, lookdownShiftImpact(_oversampleFactor, fft_size, linesPerBlock, shiftImpact); - //filter objects which will be used for azimuth and range common band filtering - isce3::signal::Filter azimuthFilter; - isce3::signal::Filter rangeFilter; - // Declare valarray for range frequencies used by filter std::valarray rangeFrequencies; @@ -493,35 +523,10 @@ crossmul(isce3::io::Raster& refSlcRaster, // retrieve the original filter to revert the range windowing effects std::valarray> originalRangeFilter; - // Declare valarray for range and azimuth doppler centroids used by filter - std::valarray refDoppCentroids; - std::valarray secDoppCentroids; - - size_t maxKernelSize = -1; if (_doCommonAzimuthBandFilter) { // Allocate storage for azimuth spectrum refAzimuthSpectrum.resize(spectrumSize); secAzimuthSpectrum.resize(spectrumSize); - - // Compute the mean doppler centroid of each slant range for - // the reference and secondary images for each slant range - refDoppCentroids.resize(fft_size); refDoppCentroids = 0.0; - secDoppCentroids.resize(fft_size); secDoppCentroids = 0.0; - - std::cout << " - compute the doppler centroids\n"; - _compute_DoppCentroids(_refDoppler, _secDoppler, - rngOffsetRaster, - aziOffsetRaster, - refDoppCentroids, - secDoppCentroids); - - maxKernelSize = _maximum_kernel_size(refDoppCentroids, - secDoppCentroids, - _azimuthBandwidth, - _prf, - _windowParameter, - azimuthFilter); - std::cout << " - max kernel size = " << maxKernelSize << std::endl; } if (_doCommonRangeBandFilter) { From 6c0dfcfeaaed3c2753f2ab3dcd2ca203f0700059 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 30 Nov 2023 22:49:22 +0000 Subject: [PATCH 045/106] overlap size determination --- cxx/isce3/signal/Crossmul.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index b27bdc586..362b034cb 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -350,6 +350,20 @@ crossmul(isce3::io::Raster& refSlcRaster, std::cout << " - max kernel size = " << maxKernelSize << std::endl; } + // to ensure the overlap size is an integer multiple number of azimuth looks. + size_t kernelSize = ((maxKernelSize + _azimuthLooks) / _azimuthLooks); + + // Force the kernel size to be even + kernelSize = kernelSize ? (kernelSize%2 == 0) : kernelSize + 1; + + // The overlap size will be even + const size_t overlapSize = kernelSize * _azimuthLooks; + + // Re-compute the lines per block to account the overlaps between two blocks + linesPerBlock = (_linesPerBlock / _azimuthLooks) * _azimuthLooks; + _linesPerBlock = linesPerBlock + overlapSize; + linesPerBlock = _linesPerBlock; + const auto output_rows = ifgRaster.length(); const auto output_cols = ifgRaster.width(); if (_multiLookEnabled) { From 3d9d50a84698a8ed2affb8f57b8217b0347a5b85 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Fri, 1 Dec 2023 00:46:56 +0000 Subject: [PATCH 046/106] process by block with overlap --- cxx/isce3/signal/Crossmul.cpp | 62 ++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 362b034cb..d3c57b319 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -327,7 +327,7 @@ crossmul(isce3::io::Raster& refSlcRaster, std::valarray refDoppCentroids; std::valarray secDoppCentroids; - size_t maxKernelSize = -1; + int maxKernelSize = 0; if (_doCommonAzimuthBandFilter) { // Compute the mean doppler centroid of each slant range for // the reference and secondary images for each slant range @@ -351,13 +351,13 @@ crossmul(isce3::io::Raster& refSlcRaster, } // to ensure the overlap size is an integer multiple number of azimuth looks. - size_t kernelSize = ((maxKernelSize + _azimuthLooks) / _azimuthLooks); + maxKernelSize = (maxKernelSize + _azimuthLooks) / _azimuthLooks; // Force the kernel size to be even - kernelSize = kernelSize ? (kernelSize%2 == 0) : kernelSize + 1; + maxKernelSize = (maxKernelSize%2 == 0) ? maxKernelSize : maxKernelSize + 1; // The overlap size will be even - const size_t overlapSize = kernelSize * _azimuthLooks; + const int overlapSize = maxKernelSize * _azimuthLooks; // Re-compute the lines per block to account the overlaps between two blocks linesPerBlock = (_linesPerBlock / _azimuthLooks) * _azimuthLooks; @@ -418,10 +418,10 @@ crossmul(isce3::io::Raster& refSlcRaster, looksObj.ncolsLooked(ncolsMultiLooked); // number of blocks to process - size_t nblocks = nrows / linesPerBlock; + size_t nblocks = nrows / (linesPerBlock - overlapSize); if (nblocks == 0) { nblocks = 1; - } else if (nrows % (nblocks * linesPerBlock) != 0) { + } else if (nrows % (nblocks * (linesPerBlock - overlapSize)) != 0) { nblocks += 1; } @@ -590,7 +590,7 @@ crossmul(isce3::io::Raster& refSlcRaster, for (size_t block = 0; block < nblocks; ++block) { std::cout << "block: " << block << std::endl; // start row for this block - const auto rowStart = block * linesPerBlock; + const auto rowStart = block * (linesPerBlock - overlapSize); //number of lines of data in this block. blockRowsData<= linesPerBlock //Note that linesPerBlock is fixed number of lines @@ -758,8 +758,26 @@ crossmul(isce3::io::Raster& refSlcRaster, looksObj.ncols(ncols); looksObj.colsLooks(_rangeLooks); looksObj.multilook(ifgram, ifgramMultiLooked); - ifgRaster.setBlock(ifgramMultiLooked, 0, rowStart/_azimuthLooks, - ncols/_rangeLooks, blockRowsData/_azimuthLooks); + + unsigned long rowNewStart = 0; + std::slice dataSlice = std::slice(0,ncolsMultiLooked * (linesPerBlock - overlapSize/2) / _azimuthLooks, 1); + if (block > 0) { + rowNewStart = (rowStart + overlapSize/2)/_azimuthLooks; + if (block != (nblocks - 1)) { + dataSlice = std::slice((overlapSize/2)/_azimuthLooks*ncolsMultiLooked, + ncolsMultiLooked * (blockRowsData - overlapSize) / _azimuthLooks, 1); + } else { + dataSlice = std::slice((overlapSize/2)/_azimuthLooks*ncolsMultiLooked, + ncolsMultiLooked * (blockRowsData - overlapSize/2) / _azimuthLooks, 1); + } + } + + // set the block of interferogram + std::valarray> ifgramSlice = ifgramMultiLooked[dataSlice]; + std::cout << ifgramSlice.size() << "," << ifgramMultiLooked.size() << std::endl; + + ifgRaster.setBlock(ifgramSlice, 0, rowNewStart, + ncols/_rangeLooks,ifgramSlice.size()/(ncols/_rangeLooks)); // multilook SLC to power for coherence computation // refPowerLooked = average(abs(refSlc)^2) @@ -783,18 +801,32 @@ crossmul(isce3::io::Raster& refSlcRaster, } // set coherence raster - coherenceRaster.setBlock(coherence, 0, rowStart/_azimuthLooks, - ncols/_rangeLooks, blockRowsData/_azimuthLooks); + std::valarray coherenceSlice =coherence[dataSlice]; + coherenceRaster.setBlock(coherenceSlice, 0, rowNewStart, + ncols/_rangeLooks,coherenceSlice.size()/(ncols/_rangeLooks)); } else { + + unsigned long rowNewStart = 0; + std::slice dataSlice = std::slice(0, linesPerBlock - overlapSize/2, 1); + if (block > 0) { + rowNewStart = rowStart + overlapSize/2; + if (block != (nblocks - 1)) { + dataSlice = std::slice((overlapSize/2)*ncols,blockRowsData - overlapSize, 1); + } else { + dataSlice = std::slice((overlapSize/2)*ncols,blockRowsData - overlapSize/2, 1); + } + } + // set the block of interferogram - ifgRaster.setBlock(ifgram, 0, rowStart, ncols, blockRowsData); + std::valarray> ifgramSlice =ifgram[dataSlice]; + ifgRaster.setBlock(ifgram, 0, rowNewStart, ncols, ifgramSlice.size()/ncols); // fill coherence with ones (no need to compute result) coherence = 1.0; - // set the block of coherence - coherenceRaster.setBlock(coherence, 0, rowStart, ncols, - blockRowsData); + std::valarray coherenceSlice =coherence[dataSlice]; + coherenceRaster.setBlock(coherence, 0, rowNewStart, ncols, + coherenceSlice.size()/ncols); } } From 681754552c11a03c78a2cdc7df68d44383422433 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 4 Dec 2023 21:48:42 +0000 Subject: [PATCH 047/106] finish the block with overlap processing --- cxx/isce3/signal/Crossmul.cpp | 150 +++++++++++++++++++++------------- cxx/isce3/signal/Crossmul.h | 16 ++++ 2 files changed, 108 insertions(+), 58 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index d3c57b319..d3c3fea84 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -159,6 +159,50 @@ rangeCommonBandFilter(std::valarray> &refSlc, return (_rangeBandwidth - frequencyShift); } +/** +* @param[in, out] refSlc a block of the reference SLC to be filtered +* @param[in, out] secSlc a block of second SLC to be filtered +* @param[in] refDoppCentroids reference doppler centroid +* @param[in] secDoppCentroids secondary doppler centroid +* @param[in, out] refAzimuthSpectrum spectrum of the reference after filtering +* @param[in, out] secAzimuthSpectrum spectrum of the secondary after filtering +* @param[in] azimuthFilter a filter object +* @param[in] blockLength number of rows +* @param[in] ncols number of columns +*/ +double isce3::signal::Crossmul:: +azimuthCommonBandFilter(std::valarray> &refSlc, + std::valarray> &secSlc, + const std::valarray &refDoppCentroids, + const std::valarray &secDoppCentroids, + std::valarray> &refAzimuthSpectrum, + std::valarray> &secAzimuthSpectrum, + isce3::signal::Filter &azimuthFilter, + size_t blockRows, + size_t ncols) +{ + std::string filterType = _windowType; + + // Construct azimuth common band filter for a block of data of the reference + double processedAzimuthBandwidth = azimuthFilter.constructAzimuthCommonbandFilter( + refDoppCentroids, secDoppCentroids, + _azimuthBandwidth, + _prf, _windowParameter, refSlc, refAzimuthSpectrum, ncols, + blockRows, filterType); + azimuthFilter.filter(refSlc, refAzimuthSpectrum); + + // Construct azimuth common band filter for a block of data of the secondary + azimuthFilter.constructAzimuthCommonbandFilter( + refDoppCentroids, secDoppCentroids, + _azimuthBandwidth, + _prf, _windowParameter, secSlc, secAzimuthSpectrum, ncols, + blockRows, filterType); + + azimuthFilter.filter(secSlc, secAzimuthSpectrum); + + return processedAzimuthBandwidth; +} + /** * @param[in] refDopplerCentroids doppler centroid frequency for reference * @param[in] secDopplerCentroids doppler centroid frequency for secondary @@ -178,7 +222,7 @@ isce3::signal::Crossmul::_maximum_kernel_size(std::valarray &refDopplerC const double stopatt, const double transition_width) { - int max_kernel_size = -1; + int max_kernel_size = 0; // Loop over columns to get the maximum kernel size #pragma omp parallel for reduction(max:max_kernel_size) @@ -326,8 +370,9 @@ crossmul(isce3::io::Raster& refSlcRaster, // Declare valarray for range and azimuth doppler centroids used by filter std::valarray refDoppCentroids; std::valarray secDoppCentroids; - int maxKernelSize = 0; + int overlapSize = 0; + if (_doCommonAzimuthBandFilter) { // Compute the mean doppler centroid of each slant range for // the reference and secondary images for each slant range @@ -348,21 +393,23 @@ crossmul(isce3::io::Raster& refSlcRaster, _windowParameter, azimuthFilter); std::cout << " - max kernel size = " << maxKernelSize << std::endl; - } - // to ensure the overlap size is an integer multiple number of azimuth looks. - maxKernelSize = (maxKernelSize + _azimuthLooks) / _azimuthLooks; + // to ensure the overlap size is an integer multiple number of azimuth looks. + maxKernelSize = (maxKernelSize + _azimuthLooks) / _azimuthLooks; - // Force the kernel size to be even - maxKernelSize = (maxKernelSize%2 == 0) ? maxKernelSize : maxKernelSize + 1; + // Force the kernel size to be even + maxKernelSize = (maxKernelSize%2 == 0) ? maxKernelSize : maxKernelSize + 1; - // The overlap size will be even - const int overlapSize = maxKernelSize * _azimuthLooks; + // The overlap size will be even + overlapSize = maxKernelSize * _azimuthLooks; - // Re-compute the lines per block to account the overlaps between two blocks - linesPerBlock = (_linesPerBlock / _azimuthLooks) * _azimuthLooks; - _linesPerBlock = linesPerBlock + overlapSize; - linesPerBlock = _linesPerBlock; + // Re-compute the lines per block to account the overlaps between two blocks + linesPerBlock = (_linesPerBlock / _azimuthLooks) * _azimuthLooks; + _linesPerBlock = linesPerBlock + overlapSize; + + // The lines per block will be multiple times of the azimuth looks + linesPerBlock = _linesPerBlock; + } const auto output_rows = ifgRaster.length(); const auto output_cols = ifgRaster.width(); @@ -622,8 +669,8 @@ crossmul(isce3::io::Raster& refSlcRaster, } // load the range offsets that are required by flattening, - // common range and azimuth filters - if (_doFlatten || _doCommonAzimuthBandFilter || _doCommonRangeBandFilter) { + // common range filters + if (_doFlatten || _doCommonRangeBandFilter) { std::valarray offsetLine(ncols); for (size_t line = 0; line < blockRowsData; ++line) { rngOffsetRaster->getLine(offsetLine, rowStart + line); @@ -679,28 +726,11 @@ crossmul(isce3::io::Raster& refSlcRaster, } //common azimuth band-pass filter the reference and secondary SLCs - //refering to ESA InSAR tutorial-part B (https://www.esa.int/esapub/tm/tm19/TM-19_ptB.pdf on page 20 and 21) - //TODO: since there is no windowing is applied in azimuth, no need to revert - //the windowing effects, and the antenna pattern coefficients are not stored in the - //SLC yet, will wait for the implementation and revert the attena pattern then if (_doCommonAzimuthBandFilter) { - std::string filterType = _windowType; - // Construct azimuth common band filter for a block of data of the reference - _processedAzimuthBandwidth += azimuthFilter.constructAzimuthCommonbandFilter( - refDoppCentroids, secDoppCentroids, - _azimuthBandwidth, - _prf, _windowParameter, refSlc, refAzimuthSpectrum, fft_size, - linesPerBlock, filterType); - azimuthFilter.filter(refSlc, refAzimuthSpectrum); - - // Construct azimuth common band filter for a block of data of the secondary - azimuthFilter.constructAzimuthCommonbandFilter( - refDoppCentroids, secDoppCentroids, - _azimuthBandwidth, - _prf, _windowParameter, secSlc, secAzimuthSpectrum, fft_size, - linesPerBlock, filterType); - - azimuthFilter.filter(secSlc, secAzimuthSpectrum); + _processedAzimuthBandwidth += azimuthCommonBandFilter(refSlc, secSlc, + refDoppCentroids, secDoppCentroids, + refAzimuthSpectrum, secAzimuthSpectrum, + azimuthFilter, linesPerBlock, fft_size); } // upsample the reference and secondary SLCs @@ -759,25 +789,26 @@ crossmul(isce3::io::Raster& refSlcRaster, looksObj.colsLooks(_rangeLooks); looksObj.multilook(ifgram, ifgramMultiLooked); - unsigned long rowNewStart = 0; - std::slice dataSlice = std::slice(0,ncolsMultiLooked * (linesPerBlock - overlapSize/2) / _azimuthLooks, 1); + size_t rowNewStart = 0; + size_t nrowsMultiLooked = (linesPerBlock - overlapSize/2) / _azimuthLooks; + // The first block + std::slice dataSlice = std::slice(0,ncolsMultiLooked * nrowsMultiLooked, 1); if (block > 0) { rowNewStart = (rowStart + overlapSize/2)/_azimuthLooks; if (block != (nblocks - 1)) { + nrowsMultiLooked = (blockRowsData - overlapSize) / _azimuthLooks; dataSlice = std::slice((overlapSize/2)/_azimuthLooks*ncolsMultiLooked, - ncolsMultiLooked * (blockRowsData - overlapSize) / _azimuthLooks, 1); - } else { + ncolsMultiLooked * nrowsMultiLooked, 1); + } else { // The last block + nrowsMultiLooked = (blockRowsData - overlapSize/2) / _azimuthLooks; dataSlice = std::slice((overlapSize/2)/_azimuthLooks*ncolsMultiLooked, - ncolsMultiLooked * (blockRowsData - overlapSize/2) / _azimuthLooks, 1); + ncolsMultiLooked * nrowsMultiLooked, 1); } } - // set the block of interferogram - std::valarray> ifgramSlice = ifgramMultiLooked[dataSlice]; - std::cout << ifgramSlice.size() << "," << ifgramMultiLooked.size() << std::endl; - + std::valarray> ifgramSlice= ifgramMultiLooked[dataSlice]; ifgRaster.setBlock(ifgramSlice, 0, rowNewStart, - ncols/_rangeLooks,ifgramSlice.size()/(ncols/_rangeLooks)); + ncolsMultiLooked, nrowsMultiLooked); // multilook SLC to power for coherence computation // refPowerLooked = average(abs(refSlc)^2) @@ -801,32 +832,35 @@ crossmul(isce3::io::Raster& refSlcRaster, } // set coherence raster - std::valarray coherenceSlice =coherence[dataSlice]; + std::valarray coherenceSlice = coherence[dataSlice]; coherenceRaster.setBlock(coherenceSlice, 0, rowNewStart, - ncols/_rangeLooks,coherenceSlice.size()/(ncols/_rangeLooks)); + ncolsMultiLooked,nrowsMultiLooked); } else { - unsigned long rowNewStart = 0; - std::slice dataSlice = std::slice(0, linesPerBlock - overlapSize/2, 1); + size_t rowNewStart = 0; + size_t nrowsValid = linesPerBlock - overlapSize/2; + std::slice dataSlice = std::slice(0, nrowsValid, 1); if (block > 0) { rowNewStart = rowStart + overlapSize/2; if (block != (nblocks - 1)) { - dataSlice = std::slice((overlapSize/2)*ncols,blockRowsData - overlapSize, 1); - } else { - dataSlice = std::slice((overlapSize/2)*ncols,blockRowsData - overlapSize/2, 1); + nrowsValid = blockRowsData - overlapSize; + dataSlice = std::slice((overlapSize/2)*ncols,nrowsValid, 1); + } else { // the last block + nrowsValid = blockRowsData - overlapSize/2; + dataSlice = std::slice((overlapSize/2)*ncols,nrowsValid, 1); } } + std::valarray> ifgramSlice= ifgram[dataSlice]; // set the block of interferogram - std::valarray> ifgramSlice =ifgram[dataSlice]; - ifgRaster.setBlock(ifgram, 0, rowNewStart, ncols, ifgramSlice.size()/ncols); + ifgRaster.setBlock(ifgramSlice, 0, rowNewStart, ncols, nrowsValid); // fill coherence with ones (no need to compute result) coherence = 1.0; // set the block of coherence - std::valarray coherenceSlice =coherence[dataSlice]; - coherenceRaster.setBlock(coherence, 0, rowNewStart, ncols, - coherenceSlice.size()/ncols); + std::valarray coherenceSlice = coherence[dataSlice]; + coherenceRaster.setBlock(coherenceSlice, 0, rowNewStart, ncols, + nrowsValid); } } diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index d6a4ada0d..103fc675c 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -208,6 +208,22 @@ class isce3::signal::Crossmul { size_t blockRows, size_t ncols); + /** Azimuth common band filtering and return the new bandwidth + //refering to ESA InSAR tutorial-part B (https://www.esa.int/esapub/tm/tm19/TM-19_ptB.pdf on page 20 and 21) + //TODO: since there is no windowing is applied in azimuth, no need to revert + //the windowing effects, and the antenna pattern coefficients are not stored in the + //SLC yet, will wait for the implementation and revert the attena pattern then + */ + double azimuthCommonBandFilter(std::valarray> &refSlc, + std::valarray> &secSlc, + const std::valarray &refDoppCentroids, + const std::valarray &secDoppCentroids, + std::valarray> &refAzimuthSpectrum, + std::valarray> &secAzimuthSpectrum, + isce3::signal::Filter &azimuthFilter, + size_t blockRows, + size_t ncols); + private: void _compute_DoppCentroids(const isce3::core::LUT2d & refDoppler, const isce3::core::LUT2d & secDoppler, From e3b71d4736dfbda43d3238df2d5179fea491283f Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 4 Dec 2023 22:10:13 +0000 Subject: [PATCH 048/106] optimize the performance --- cxx/isce3/signal/Crossmul.cpp | 27 ++++----------- cxx/isce3/signal/Filter.cpp | 55 +++++++++++++++++++++---------- cxx/isce3/signal/Filter.h | 18 +++++----- tests/cxx/isce3/signal/filter.cpp | 1 - 4 files changed, 54 insertions(+), 47 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index d3c3fea84..758d534de 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -128,27 +128,17 @@ rangeCommonBandFilter(std::valarray> &refSlc, rngFilter.constructRangeCommonbandFilter(_rangeSamplingFrequency, filterCenterFrequency, filterBandwidth, - refSlc, - refSpectrum, ncols, blockLength, _windowType, _windowParameter); // low pass filter the ref slc + rngFilter.InitCommonRangeFilter(refSlc,refSpectrum, ncols, blockLength); rngFilter.filter(refSlc, refSpectrum); - // low band pass the sec slc - rngFilter.constructRangeCommonbandFilter(_rangeSamplingFrequency, - filterCenterFrequency, - filterBandwidth, - secSlc, - secSpectrum, - ncols, - blockLength, - _windowType, - _windowParameter); - + // low pass filter the sec slc + rngFilter.InitCommonRangeFilter(secSlc,secSpectrum, ncols, blockLength); rngFilter.filter(secSlc, secSpectrum); // restore the original phase without the geometry phase @@ -187,17 +177,14 @@ azimuthCommonBandFilter(std::valarray> &refSlc, double processedAzimuthBandwidth = azimuthFilter.constructAzimuthCommonbandFilter( refDoppCentroids, secDoppCentroids, _azimuthBandwidth, - _prf, _windowParameter, refSlc, refAzimuthSpectrum, ncols, + _prf, _windowParameter, ncols, blockRows, filterType); + + azimuthFilter.initiateAzimuthFilter(refSlc, refAzimuthSpectrum, ncols, blockRows); azimuthFilter.filter(refSlc, refAzimuthSpectrum); // Construct azimuth common band filter for a block of data of the secondary - azimuthFilter.constructAzimuthCommonbandFilter( - refDoppCentroids, secDoppCentroids, - _azimuthBandwidth, - _prf, _windowParameter, secSlc, secAzimuthSpectrum, ncols, - blockRows, filterType); - + azimuthFilter.initiateAzimuthFilter(secSlc, secAzimuthSpectrum, ncols, blockRows); azimuthFilter.filter(secSlc, secAzimuthSpectrum); return processedAzimuthBandwidth; diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 702c11427..8b57e9ab3 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -138,6 +138,41 @@ constructRangeBandpassFilter(double rangeSamplingFrequency, } } +/** + * @param[in] signal a block of data to filter + * @param[in] spectrum a block of spectrum, which is internally used for FFT computations + * @param[in] ncols number of columns of the block of data + * @param[in] nrows number of rows of the block of data +*/ +template +void +isce3::signal::Filter::InitCommonRangeFilter(std::valarray> &signal, + std::valarray> &spectrum, + size_t ncols, + size_t nrows) +{ + _signal.forwardRangeFFT(signal, spectrum, ncols, nrows); + _signal.inverseRangeFFT(spectrum, signal, ncols, nrows); +} + +/** + * @param[in] signal a block of data to filter + * @param[in] spectrum a block of spectrum, which is internally used for FFT computations + * @param[in] ncols number of columns of the block of data + * @param[in] nrows number of rows of the block of data +*/ +template +void +isce3::signal::Filter::InitCommonAzimuthFilter(std::valarray> &signal, + std::valarray> &spectrum, + size_t ncols, + size_t nrows) +{ + _signal.forwardAzimuthFFT(signal, spectrum, ncols, nrows); + _signal.inverseAzimuthFFT(spectrum, signal, ncols, nrows); +} + + /** * @param[in] rangeSamplingFrequency range sampling frequency * @param[in] subBandCenterFrequency a vector of center frequencies for each band @@ -155,15 +190,11 @@ void isce3::signal::Filter::constructRangeCommonbandFilter(const double rangeSamplingFrequency, const double subBandCenterFrequency, const double subBandBandwidth, - std::valarray> &signal, - std::valarray> &spectrum, size_t ncols, size_t nrows, const std::string filterType, const double windowParameter) { - _signal.forwardRangeFFT(signal, spectrum, ncols, nrows); - _signal.inverseRangeFFT(spectrum, signal, ncols, nrows); int fft_size = ncols; @@ -419,8 +450,6 @@ constructAzimuthCommonbandFilter(const std::valarray & refDoppler, double bandwidth, double prf, double beta, - std::valarray> &signal, - std::valarray> &spectrum, size_t ncols, size_t nrows, std::string filterType) @@ -430,7 +459,7 @@ constructAzimuthCommonbandFilter(const std::valarray & refDoppler, refDoppler, secDoppler, bandwidth, - prf, beta, signal, spectrum, + prf, beta, ncols, nrows); } else if (filterType=="kaiser"){ @@ -438,7 +467,7 @@ constructAzimuthCommonbandFilter(const std::valarray & refDoppler, refDoppler, secDoppler, bandwidth, - prf, beta, signal, spectrum, + prf, beta, ncols, nrows); } else{ std::cout << filterType << " filter has not been implemented" << std::endl; @@ -465,8 +494,6 @@ constructAzimuthCommonbandCosineFilter(const std::valarray & refDoppler, double bandwidth, double prf, double beta, - std::valarray> &signal, - std::valarray> &spectrum, size_t ncols, size_t nrows) { @@ -538,9 +565,6 @@ constructAzimuthCommonbandCosineFilter(const std::valarray & refDoppler, std::cout << " - mean doppler center freq:" << meanDopCenterFreq << std::endl; std::cout << " - mean doppler center freq shift:" << meanDopCenterFreqShift << std::endl; - _signal.forwardAzimuthFFT(signal, spectrum, ncols, nrows); - _signal.inverseAzimuthFFT(spectrum, signal, ncols, nrows); - return (bandwidth - meanDopCenterFreqShift); } @@ -563,8 +587,6 @@ constructAzimuthCommonbandKaiserFilter(const std::valarray & refDoppler, double bandwidth, double prf, double beta, - std::valarray> &signal, - std::valarray> &spectrum, size_t ncols, size_t nrows) { @@ -628,9 +650,6 @@ constructAzimuthCommonbandKaiserFilter(const std::valarray & refDoppler, std::cout << " - mean doppler center freq (Hz):" << meanDopCenterFreq << std::endl; std::cout << " - mean doppler center freq shift (Hz):" << meanDopCenterFreqShift << std::endl; - _signal.forwardAzimuthFFT(signal, spectrum, ncols, nrows); - _signal.inverseAzimuthFFT(spectrum, signal, ncols, nrows); - return (bandwidth - meanDopCenterFreqShift); } diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index ea443b848..03fcfe9f6 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -94,12 +94,15 @@ class isce3::signal::Filter { double beta, std::valarray>& _filter1D); + /** Initialize the range FFT filter*/ + void InitCommonRangeFilter(std::valarray> &signal, + std::valarray> &spectrum, + size_t ncols, size_t nrows); + /** Construct the range common band filter*/ void constructRangeCommonbandFilter(const double rangeSamplingFrequency, const double subBandCenterFrequency, const double subBandBandwidths, - std::valarray> &signal, - std::valarray> &spectrum, size_t ncols, size_t nrows, const std::string filterType, @@ -113,14 +116,17 @@ class isce3::signal::Filter { const double beta, std::valarray>& filter1D); + /** Initialize the azimuth common FFT filter*/ + void InitCommonAzimuthFilter(std::valarray> &signal, + std::valarray> &spectrum, + size_t ncols, size_t nrows); + /** Construct azimuth common band filter*/ double constructAzimuthCommonbandFilter(const std::valarray & refDoppler, const std::valarray & secDoppler, double bandwidth, double prf, double beta, - std::valarray> &signal, - std::valarray> &spectrum, size_t ncols, size_t nrows, std::string filterType); @@ -131,8 +137,6 @@ class isce3::signal::Filter { double bandwidth, double prf, double beta, - std::valarray> &signal, - std::valarray> &spectrum, size_t ncols, size_t nrows); @@ -142,8 +146,6 @@ class isce3::signal::Filter { double bandwidth, double prf, double beta, - std::valarray> &signal, - std::valarray> &spectrum, size_t ncols, size_t nrows); diff --git a/tests/cxx/isce3/signal/filter.cpp b/tests/cxx/isce3/signal/filter.cpp index 18b6a183f..ec56e05cc 100644 --- a/tests/cxx/isce3/signal/filter.cpp +++ b/tests/cxx/isce3/signal/filter.cpp @@ -59,7 +59,6 @@ TEST(Filter, constructAzimuthCommonbandFilter) commonAzimuthBandwidth, prf, beta, - refSlc, refSpectrum, ncols, blockRows); filter.writeFilter(ncols, blockRows); From 989f5d581d59807ace424603adcd39ebc7a3b0f2 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 4 Dec 2023 22:50:01 +0000 Subject: [PATCH 049/106] remove .vscode --- .vscode/settings.json | 69 ------------------------------------------- 1 file changed, 69 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 9403e2971..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "files.associations": { - "any": "cpp", - "array": "cpp", - "atomic": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "chrono": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "complex": "cpp", - "condition_variable": "cpp", - "csignal": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "list": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "map": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "regex": "cpp", - "set": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "new": "cpp", - "ostream": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "cinttypes": "cpp", - "typeindex": "cpp", - "typeinfo": "cpp", - "valarray": "cpp", - "variant": "cpp", - "*.icc": "cpp" - } -} \ No newline at end of file From 12f04cf57ba29f85f0752d72c575ecfda4f6acca Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 4 Dec 2023 23:01:06 +0000 Subject: [PATCH 050/106] fix minors --- cxx/isce3/signal/Crossmul.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 758d534de..550379c3c 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -620,7 +620,6 @@ crossmul(isce3::io::Raster& refSlcRaster, // loop over all blocks std::cout << "nblocks : " << nblocks << std::endl; - for (size_t block = 0; block < nblocks; ++block) { std::cout << "block: " << block << std::endl; // start row for this block From 6b09a5eeeae8607394dd324935d856014c9762de Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 4 Dec 2023 23:56:26 +0000 Subject: [PATCH 051/106] initialize the crossmul variables --- cxx/isce3/signal/Crossmul.cpp | 23 ++++++++++++----------- cxx/isce3/signal/Crossmul.h | 24 ++++++++++++------------ 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 550379c3c..422fcbc8c 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -359,6 +359,7 @@ crossmul(isce3::io::Raster& refSlcRaster, std::valarray secDoppCentroids; int maxKernelSize = 0; int overlapSize = 0; + int halfOverlapSize = 0; if (_doCommonAzimuthBandFilter) { // Compute the mean doppler centroid of each slant range for @@ -389,7 +390,7 @@ crossmul(isce3::io::Raster& refSlcRaster, // The overlap size will be even overlapSize = maxKernelSize * _azimuthLooks; - + halfOverlapSize = overlapSize / 2; // Re-compute the lines per block to account the overlaps between two blocks linesPerBlock = (_linesPerBlock / _azimuthLooks) * _azimuthLooks; _linesPerBlock = linesPerBlock + overlapSize; @@ -776,18 +777,18 @@ crossmul(isce3::io::Raster& refSlcRaster, looksObj.multilook(ifgram, ifgramMultiLooked); size_t rowNewStart = 0; - size_t nrowsMultiLooked = (linesPerBlock - overlapSize/2) / _azimuthLooks; + size_t nrowsMultiLooked = (linesPerBlock - halfOverlapSize) / _azimuthLooks; // The first block std::slice dataSlice = std::slice(0,ncolsMultiLooked * nrowsMultiLooked, 1); if (block > 0) { - rowNewStart = (rowStart + overlapSize/2)/_azimuthLooks; + rowNewStart = (rowStart + halfOverlapSize)/_azimuthLooks; if (block != (nblocks - 1)) { nrowsMultiLooked = (blockRowsData - overlapSize) / _azimuthLooks; - dataSlice = std::slice((overlapSize/2)/_azimuthLooks*ncolsMultiLooked, + dataSlice = std::slice(halfOverlapSize/_azimuthLooks*ncolsMultiLooked, ncolsMultiLooked * nrowsMultiLooked, 1); } else { // The last block - nrowsMultiLooked = (blockRowsData - overlapSize/2) / _azimuthLooks; - dataSlice = std::slice((overlapSize/2)/_azimuthLooks*ncolsMultiLooked, + nrowsMultiLooked = (blockRowsData - halfOverlapSize) / _azimuthLooks; + dataSlice = std::slice(halfOverlapSize/_azimuthLooks*ncolsMultiLooked, ncolsMultiLooked * nrowsMultiLooked, 1); } } @@ -824,16 +825,16 @@ crossmul(isce3::io::Raster& refSlcRaster, } else { size_t rowNewStart = 0; - size_t nrowsValid = linesPerBlock - overlapSize/2; + size_t nrowsValid = linesPerBlock - halfOverlapSize; std::slice dataSlice = std::slice(0, nrowsValid, 1); if (block > 0) { - rowNewStart = rowStart + overlapSize/2; + rowNewStart = rowStart + halfOverlapSize; if (block != (nblocks - 1)) { nrowsValid = blockRowsData - overlapSize; - dataSlice = std::slice((overlapSize/2)*ncols,nrowsValid, 1); + dataSlice = std::slice(halfOverlapSize*ncols,nrowsValid, 1); } else { // the last block - nrowsValid = blockRowsData - overlapSize/2; - dataSlice = std::slice((overlapSize/2)*ncols,nrowsValid, 1); + nrowsValid = blockRowsData - halfOverlapSize; + dataSlice = std::slice(halfOverlapSize*ncols,nrowsValid, 1); } } diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 103fc675c..26ed674c5 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -248,22 +248,22 @@ class isce3::signal::Crossmul { isce3::core::LUT2d _secDoppler; // range pixel spacing in meters - double _rangePixelSpacing; + double _rangePixelSpacing = 0.0; // reference starting range - double _refStartRange; + double _refStartRange = 0.0; // reference starting azimuth time - double _refStartAzimuthTime; + double _refStartAzimuthTime = 0.0; // secondary starting range - double _secStartRange; + double _secStartRange = 0.0; // secondary starting azimuth time - double _secStartAzimuthTime; + double _secStartAzimuthTime = 0.0; // radar wavelength in meters - double _wavelength; + double _wavelength = 0.0; // number of range looks int _rangeLooks = 1; @@ -280,10 +280,10 @@ class isce3::signal::Crossmul { bool _doCommonAzimuthBandFilter = false; // Azimuth bandwidth in Hz - double _azimuthBandwidth; + double _azimuthBandwidth = 0.0; // Processed azimuth bandwidth after the common band filtering in Hz - double _processedAzimuthBandwidth; + double _processedAzimuthBandwidth = 0.0; // Window type std::string _windowType = "kaiser"; @@ -295,16 +295,16 @@ class isce3::signal::Crossmul { bool _doCommonRangeBandFilter = false; //pulse repetition frequency, in Hz - double _prf; + double _prf = 0.0; // range samping frequency, in Hz - double _rangeSamplingFrequency; + double _rangeSamplingFrequency = 0.0; // range signal bandwidth in Hz - double _rangeBandwidth; + double _rangeBandwidth = 0.0; // Processed range bandwidth after the common band filtering in Hz - double _processedRangeBandwidth; + double _processedRangeBandwidth = 0.0; // number of lines per block size_t _linesPerBlock = 1024; From fe50f96ce1b1fb1fdbbb9dfd797bab0c203520ba Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 5 Dec 2023 01:06:08 +0000 Subject: [PATCH 052/106] fix minors --- cxx/isce3/signal/Crossmul.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 422fcbc8c..77250e2f0 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -173,17 +173,18 @@ azimuthCommonBandFilter(std::valarray> &refSlc, { std::string filterType = _windowType; - // Construct azimuth common band filter for a block of data of the reference + // Construct azimuth common bandpass filter for both reference and secondary double processedAzimuthBandwidth = azimuthFilter.constructAzimuthCommonbandFilter( refDoppCentroids, secDoppCentroids, _azimuthBandwidth, _prf, _windowParameter, ncols, blockRows, filterType); + // Filter a block of data of the reference azimuthFilter.initiateAzimuthFilter(refSlc, refAzimuthSpectrum, ncols, blockRows); azimuthFilter.filter(refSlc, refAzimuthSpectrum); - // Construct azimuth common band filter for a block of data of the secondary + // Filter a block of data of the secondary azimuthFilter.initiateAzimuthFilter(secSlc, secAzimuthSpectrum, ncols, blockRows); azimuthFilter.filter(secSlc, secAzimuthSpectrum); @@ -391,7 +392,8 @@ crossmul(isce3::io::Raster& refSlcRaster, // The overlap size will be even overlapSize = maxKernelSize * _azimuthLooks; halfOverlapSize = overlapSize / 2; - // Re-compute the lines per block to account the overlaps between two blocks + + // Compute the lines per block to account for the overlaps between two blocks linesPerBlock = (_linesPerBlock / _azimuthLooks) * _azimuthLooks; _linesPerBlock = linesPerBlock + overlapSize; @@ -712,7 +714,7 @@ crossmul(isce3::io::Raster& refSlcRaster, rangeFrequencies, rangeFilter, linesPerBlock, fft_size); } - //common azimuth band-pass filter the reference and secondary SLCs + // Apply the azimuth common band-pass filter to the reference and secondary SLCs if (_doCommonAzimuthBandFilter) { _processedAzimuthBandwidth += azimuthCommonBandFilter(refSlc, secSlc, refDoppCentroids, secDoppCentroids, @@ -824,6 +826,7 @@ crossmul(isce3::io::Raster& refSlcRaster, ncolsMultiLooked,nrowsMultiLooked); } else { + // The first block size_t rowNewStart = 0; size_t nrowsValid = linesPerBlock - halfOverlapSize; std::slice dataSlice = std::slice(0, nrowsValid, 1); From 07a4fc81a6e40a206efc7e493a4bcdee31993fb3 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 7 Dec 2023 20:57:49 +0000 Subject: [PATCH 053/106] add the check of flatten_path --- cxx/isce3/signal/Crossmul.h | 4 ++-- python/packages/nisar/workflows/crossmul.py | 2 +- python/packages/nisar/workflows/crossmul_runconfig.py | 6 ++++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 26ed674c5..128646db5 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -26,8 +26,8 @@ class isce3::signal::Crossmul { * \param[in] secSlcRaster input raster of secondary SLC * \param[out] ifgRaster output interferogram raster * \param[out] coherenceRaster output coherence raster - * \param[in] rngOffsetRaster optional pointer to range offset raster - * \param[in] aziOffsetRaster optional pointer to azimuth offset raster + * \param[in] rngOffsetRaster optional pointer to range offset raster, in pixels + * \param[in] aziOffsetRaster optional pointer to azimuth offset raster, in pixels * */ void crossmul(isce3::io::Raster& refSlcRaster, diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index c1877f030..8775a154e 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -69,7 +69,7 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', crossmul = isce3.cuda.signal.Crossmul() if do_common_range_band_filter or do_common_azimuth_band_filter: - raise NotImplementedError("Common band filers have not been implemented for GPU") + raise NotImplementedError("Common band filters have not been implemented for GPU") else: crossmul = isce3.signal.Crossmul() # do common range band filter diff --git a/python/packages/nisar/workflows/crossmul_runconfig.py b/python/packages/nisar/workflows/crossmul_runconfig.py index 98c53f312..bb4605709 100644 --- a/python/packages/nisar/workflows/crossmul_runconfig.py +++ b/python/packages/nisar/workflows/crossmul_runconfig.py @@ -62,8 +62,10 @@ def yaml_check(self, resample_type): # flatten defaults to bool True # flatten_path defaults to scratch_path flatten = crossmul_cfg['flatten'] - do_common_band_filter = crossmul_cfg['common_band_range_filter'] - + do_common_band_range_filter = crossmul_cfg['common_band_range_filter'] + do_common_band_azimuth_filter = crossmul_cfg['common_band_azimuth_filter'] + do_common_band_filter = \ + do_common_band_range_filter or do_common_band_azimuth_filter if flatten or do_common_band_filter: if 'flatten_path' in crossmul_cfg: flatten_path = crossmul_cfg['flatten_path'] From fb1aad00f531bea4423dc578fc2cf98c8b3374ff Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 7 Dec 2023 21:12:03 +0000 Subject: [PATCH 054/106] remove the range samping frequency in pybinding --- cxx/isce3/signal/Crossmul.cpp | 5 ++++- cxx/isce3/signal/Crossmul.h | 9 ++------- python/extensions/pybind_isce3/signal/Crossmul.cpp | 3 --- python/packages/nisar/workflows/crossmul.py | 4 ++-- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 77250e2f0..bea2810f0 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -571,9 +571,12 @@ crossmul(isce3::io::Raster& refSlcRaster, std::valarray> refAzimuthSpectrum; std::valarray> secAzimuthSpectrum; - // retrieve the original filter to revert the range windowing effects + // Retrieve the original filter to revert the range windowing effects std::valarray> originalRangeFilter; + // Compute the range sampling frequency in Hz using the range pixel spacing + _rangeSamplingFrequency = 1.0 / (_rangePixelSpacing*2.0/isce3::core::speed_of_light); + if (_doCommonAzimuthBandFilter) { // Allocate storage for azimuth spectrum refAzimuthSpectrum.resize(spectrumSize); diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 128646db5..ea97d55e2 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -3,6 +3,7 @@ #include "forward.h" #include +#include #include #include #include @@ -149,13 +150,7 @@ class isce3::signal::Crossmul { /** Get pulse repetition frequency (PRF), in Hz */ inline double prf() const { return _prf; } - - /** Set range sampling frequency, in Hz */ - inline void rangeSamplingFrequency(double rgSamplingFreq) { _rangeSamplingFrequency = rgSamplingFreq; } - - /** Get range sampling frequency, in Hz*/ - inline double rangeSamplingFrequency() const { return _rangeSamplingFrequency; } - + /** Set the range bandwidth in Hz*/ inline void rangeBandwidth(double rngBandwidth) { _rangeBandwidth = rngBandwidth; } diff --git a/python/extensions/pybind_isce3/signal/Crossmul.cpp b/python/extensions/pybind_isce3/signal/Crossmul.cpp index 8b4b7504c..e7acbf931 100644 --- a/python/extensions/pybind_isce3/signal/Crossmul.cpp +++ b/python/extensions/pybind_isce3/signal/Crossmul.cpp @@ -75,9 +75,6 @@ void addbinding(py::class_ & pyCrossmul) .def_property("do_flatten", py::overload_cast<>(&Crossmul::doFlatten, py::const_), py::overload_cast(&Crossmul::doFlatten)) - .def_property("range_sampling_frequency", - py::overload_cast<>(&Crossmul::rangeSamplingFrequency, py::const_), - py::overload_cast(&Crossmul::rangeSamplingFrequency)) .def_property("range_bandwidth", py::overload_cast<>(&Crossmul::rangeBandwidth, py::const_), py::overload_cast(&Crossmul::rangeBandwidth)) diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index 8775a154e..5b02fc0ed 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -121,8 +121,8 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', sec_rdr_grid = sec_slc.getRadarGrid(freq) # range sampling rate and bandwidth - crossmul.range_sampling_frequency = \ - 1.0 / (crossmul.range_pixel_spacing*2.0/isce3.core.speed_of_light) + # crossmul.range_sampling_frequency = \ + # 1.0 / (crossmul.range_pixel_spacing*2.0/isce3.core.speed_of_light) crossmul.range_bandwidth = \ ref_slc.getSwathMetadata(freq).processed_range_bandwidth # azimuth band width and PRF From 83481e1c255f3150423291b1cac19aec40109486 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 7 Dec 2023 21:25:34 +0000 Subject: [PATCH 055/106] add references to the doxygen --- cxx/isce3/signal/Crossmul.h | 9 +++------ doc/doxygen/references.bib | 12 ++++++++++-- python/packages/nisar/workflows/crossmul.py | 6 ++---- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index ea97d55e2..4a68b44dc 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -150,7 +150,7 @@ class isce3::signal::Crossmul { /** Get pulse repetition frequency (PRF), in Hz */ inline double prf() const { return _prf; } - + /** Set the range bandwidth in Hz*/ inline void rangeBandwidth(double rngBandwidth) { _rangeBandwidth = rngBandwidth; } @@ -188,9 +188,7 @@ class isce3::signal::Crossmul { inline void getPeakIndex(std::valarray data, size_t &peakIndex); - /** Range common band filtering and return the new bandwidth - The method is refering to the ESA InSAR tutorial part B. - (https://www.esa.int/esapub/tm/tm19/TM-19_ptB.pdf on page 19) + /** Range common band filtering block by block @insar2007product */ double rangeCommonBandFilter(std::valarray> &refSlc, std::valarray> &secSlc, @@ -203,8 +201,7 @@ class isce3::signal::Crossmul { size_t blockRows, size_t ncols); - /** Azimuth common band filtering and return the new bandwidth - //refering to ESA InSAR tutorial-part B (https://www.esa.int/esapub/tm/tm19/TM-19_ptB.pdf on page 20 and 21) + /** Azimuth common band filtering block by block @insar2007product //TODO: since there is no windowing is applied in azimuth, no need to revert //the windowing effects, and the antenna pattern coefficients are not stored in the //SLC yet, will wait for the implementation and revert the attena pattern then diff --git a/doc/doxygen/references.bib b/doc/doxygen/references.bib index 3e253c187..b5ddd8f22 100644 --- a/doc/doxygen/references.bib +++ b/doc/doxygen/references.bib @@ -37,6 +37,14 @@ @article{envisat2007product url={https://earth.esa.int/pub/ESA_DOC/ENVISAT/ASAR/asar.ProductHandbook.2_2.pdf}, } +@article{insar2007product, + title={InSAR processing:a practical approach}, + author={European Space Agency}, + journal={European Space}, + year={2007}, + url={https://www.esa.int/esapub/tm/tm19/TM-19_ptB.pdf}, +} + @article{small2008guide, title={Guide to ASAR geocoding}, author={Small, David and Schubert, Adrian}, @@ -155,8 +163,8 @@ @article{breit2010 @ARTICLE{small2011, author={D. {Small}}, - journal={IEEE Transactions on Geoscience and Remote Sensing}, - title={Flattening Gamma: Radiometric Terrain Correction for SAR Imagery}, + journal={IEEE Transactions on Geoscience and Remote Sensing}, + title={Flattening Gamma: Radiometric Terrain Correction for SAR Imagery}, year={2011}, volume={49}, number={8}, diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index 5b02fc0ed..200b11a04 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -120,9 +120,7 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', sec_rdr_grid = sec_slc.getRadarGrid(freq) - # range sampling rate and bandwidth - # crossmul.range_sampling_frequency = \ - # 1.0 / (crossmul.range_pixel_spacing*2.0/isce3.core.speed_of_light) + # range bandwidth crossmul.range_bandwidth = \ ref_slc.getSwathMetadata(freq).processed_range_bandwidth # azimuth band width and PRF @@ -211,7 +209,7 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', # populate the new bandwidth along azimuth and range after the common band filter # if there is no common band filter applied, the bandwith will remain the same with - # the orignal SLC bandwith + # the orignal SLC bandwidth # TODO: GPU if not use_gpu: processing_info_path = \ From a1ded91b4e6a1ee69ec67d533840f145c495b5f3 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 7 Dec 2023 21:39:50 +0000 Subject: [PATCH 056/106] move the function description to the header file --- cxx/isce3/signal/Filter.cpp | 45 ++-------------------------------- cxx/isce3/signal/Filter.h | 49 +++++++++++++++++++++++++++++++------ 2 files changed, 44 insertions(+), 50 deletions(-) diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 8b57e9ab3..6451e0ec5 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -623,7 +623,7 @@ constructAzimuthCommonbandKaiserFilter(const std::valarray & refDoppler, throw isce3::except::InvalidArgument(ISCE_SRCINFO(), "FFT size is less than the window size"); } - // Zero padding the filter on sides + // Zero padding the filter in the middle filter1D = std::complex(0.0, 0.0); for (size_t ind = halfSizeOfKaiser; ind < sizeOfKaiser; ind ++) { filter1D[ind - halfSizeOfKaiser] = kaiser[ind]; @@ -638,7 +638,7 @@ constructAzimuthCommonbandKaiserFilter(const std::valarray & refDoppler, meanDopCenterFreqShift += fshift; meanDopCenterFreq += fmid; - // Compute the filter centered at fmid + // Copy the the filter centered at fmid for (size_t i = 0; i < filter1D.size(); ++i) { _filter[i*ncols+j] = filter1D[i]; } @@ -731,12 +731,6 @@ writeFilter(size_t ncols, size_t nrows) } -/** - * @param[in] ripple Upper bound for the deviation (in dB) of the magnitude of the filter's frequency response from that of the desired filter (not including frequencies in any transition intervals). - * @param[in] width Width of transition region, normalized so that 1 corresponds to pi radians / sample. - * @param[out] n the length of the Kaiser window. - * @param[out] beta the beta parameter for the Kaiser window - */ template void isce3::signal::Filter::_kaiserord(const double ripple, const double width, @@ -760,9 +754,6 @@ isce3::signal::Filter::_kaiserord(const double ripple, const double width, beta = _kaiser_beta(A); } -/** - * @param[in] ripple The desired attenuation in the stopband and maximum ripple in the passband, in dB. - */ template double isce3::signal::Filter::_kaiser_beta(const double ripple) @@ -778,14 +769,6 @@ isce3::signal::Filter::_kaiser_beta(const double ripple) } } -/** - * @param[in] stopatt Upper bound for the deviation (in dB) of the magnitude of the filter's frequency response from that of the desired filter (not including frequencies in any transition intervals). - * @param[in] transition_width Width of transition region, normalized so that 1 corresponds to pi radians / sample. - * @param[in] force_odd_len Force to be odd length - * @param[out] n the length of the Kaiser window. - * @param[out] beta the beta parameter for the Kaiser window - * @param[out] t time samples for Kaiser filter design method - */ template void isce3::signal::Filter::_kaiser_design(const double stopatt, @@ -802,11 +785,6 @@ isce3::signal::Filter::_kaiser_design(const double stopatt, for (size_t i = 0; i < t.size(); i++) t[i] = i - (n - 1) / 2.0; } -/** - * @param[in] t time samples for Kaiser filter design method - * @param[in] beta the beta parameter for the Kaiser window - * @param[out] irf time samples for Kaiser filter design method - */ template void isce3::signal::Filter::_kaiser_irf(const std::valarray &t, @@ -823,11 +801,6 @@ isce3::signal::Filter::_kaiser_irf(const std::valarray &t, } } -/** - * @param[in] n the length of the Kaiser window. - * @param[in] beta the beta parameter for the Kaiser window - * @param[out] kaiser_window time samples for Kaiser filter design method - */ template void isce3::signal::Filter::_kaiser(const int n, @@ -845,11 +818,6 @@ isce3::signal::Filter::_kaiser(const int n, } } -/** - * @param[in] kaiser_window the Kaiser window. - * @param[in] fc the center frequency - * @param[out] shifted_kaiser_window shifted kaiser window with center frequency fc - */ template void isce3::signal::Filter::_lowpass2bandpass(const std::valarray> &kaiser_window, @@ -866,15 +834,6 @@ isce3::signal::Filter::_lowpass2bandpass(const std::valarray> } } -/** - * @param[in] bandwidth the signal bandwidth - * @param[in] fs the sampling frequency - * @param[in] beta the Kaiser window beta parameter. - * @param[in] stopatt Upper bound for the deviation (in dB) of the magnitude of the filter's frequency response from that of the desired filter (not including frequencies in any transition intervals). - * @param[in] transition_width transition width [0-1] - * @param[in] force_odd_len Force to be odd length - * @param[out] kaiser_window low bandpass kaiser window - */ template void isce3::signal::Filter::_design_shaped_lowpass_filter(const double bandwidth, diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index 03fcfe9f6..4923aa12a 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -159,14 +159,29 @@ class isce3::signal::Filter { void writeFilter(size_t ncols, size_t nrows); public: - /** Determine the filter window parameters for the Kaiser window method*/ + /** Determine the filter window parameters for the Kaiser window method + * @param[in] ripple Upper bound for the deviation (in dB) of the magnitude of the filter's frequency response from that of the desired filter (not including frequencies in any transition intervals). + * @param[in] width Width of transition region, normalized so that 1 corresponds to pi radians / sample. + * @param[out] n the length of the Kaiser window. + * @param[out] beta the beta parameter for the Kaiser window + */ void _kaiserord(const double ripple, const double width, int &n, double &beta); - /** Compute the Kaiser parameter `beta`, given the attenuation 'ripple`*/ + /** Compute the Kaiser parameter `beta`, given the attenuation 'ripple` + * @param[in] ripple The desired attenuation in the stopband and maximum ripple in the passband, in dB. + * @return beta + */ double _kaiser_beta(const double ripple); - /** Return length, shape, and time samples for Kaiser filter design method*/ + /** Return length, shape, and time samples for Kaiser filter design method + * @param[in] stopatt Upper bound for the deviation (in dB) of the magnitude of the filter's frequency response from that of the desired filter (not including frequencies in any transition intervals). + * @param[in] transition_width Width of transition region, normalized so that 1 corresponds to pi radians / sample. + * @param[in] force_odd_len Force to be odd length + * @param[out] n the length of the Kaiser window. + * @param[out] beta the beta parameter for the Kaiser window + * @param[out] t time samples for Kaiser filter design method + */ void _kaiser_design(const double stopatt, const double transition_width, const bool force_odd_len, @@ -174,22 +189,42 @@ class isce3::signal::Filter { double &beta, std::valarray &t); - /** Impulse response (Fourier transform) of Kaiser window*/ + /** Impulse response (Fourier transform) of Kaiser window + * @param[in] t time samples for Kaiser filter design method + * @param[in] beta the beta parameter for the Kaiser window + * @param[out] irf time samples for Kaiser filter design method + */ void _kaiser_irf(const std::valarray &t, const double beta, std::valarray> &irf); - /** Kaiser window with length n*/ + /** Kaiser window with length n + * @param[in] n the length of the Kaiser window. + * @param[in] beta the beta parameter for the Kaiser window + * @param[out] kaiser_window time samples for Kaiser filter design method + */ void _kaiser(const int n, const double beta, std::valarray> &kaiser_window); - /** Turn a low pass filter into a band pass filter by applying a phase ramp.*/ + /** Turn a low pass filter into a band pass filter by applying a phase ramp. + * @param[in] kaiser_window the Kaiser window. + * @param[in] fc the center frequency divded by sampling rate + * @param[out] shifted_kaiser_window shifted kaiser window with center frequency fc + */ void _lowpass2bandpass(const std::valarray> &kaiser_window, const double fc, std::valarray> &shifted_kaiser_window); - /** Design a low pass filter having a passband shaped like a window using the Kaiser method*/ + /** Design a low pass filter having a passband shaped like a window using the Kaiser method + * @param[in] bandwidth the signal bandwidth + * @param[in] fs the sampling frequency + * @param[in] beta the Kaiser window beta parameter. + * @param[in] stopatt Upper bound for the deviation (in dB) of the magnitude of the filter's frequency response from that of the desired filter (not including frequencies in any transition intervals). + * @param[in] transition_width transition width [0-1] + * @param[in] force_odd_len Force to be odd length + * @param[out] kaiser_window low bandpass kaiser window + */ void _design_shaped_lowpass_filter(const double bandwidth, const double fs, const double window_shape, From e5015b49e547864c13be94bad02adda4c83bf0a3 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 7 Dec 2023 21:54:49 +0000 Subject: [PATCH 057/106] return the tuple --- .vscode/settings.json | 68 +++++++++++++++++++++++++++++++++++ cxx/isce3/signal/Crossmul.cpp | 4 +-- cxx/isce3/signal/Filter.cpp | 10 +++--- cxx/isce3/signal/Filter.h | 6 ++-- 4 files changed, 75 insertions(+), 13 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..a8ddd9f34 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,68 @@ +{ + "files.associations": { + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "set": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "valarray": "cpp", + "variant": "cpp" + } +} \ No newline at end of file diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index bea2810f0..e66abcaae 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -232,9 +232,7 @@ isce3::signal::Crossmul::_maximum_kernel_size(std::valarray &refDopplerC "Passband + transition cannot exceed Nyquist"); } - int n = 0; - double beta = 0.0; - aziFilter._kaiserord(stopatt, tw, n, beta); + auto [n, _] = aziFilter._kaiserord(stopatt, tw); if (n > max_kernel_size) max_kernel_size = n; } } diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 6451e0ec5..1bedc3dd9 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -732,9 +732,8 @@ writeFilter(size_t ncols, size_t nrows) } template -void -isce3::signal::Filter::_kaiserord(const double ripple, const double width, - int &n, double &beta) +std::tuple +isce3::signal::Filter::_kaiserord(const double ripple, const double width) { const double A = std::abs(ripple); // in case somebody is confused as to what's meant if (A < 8) { @@ -750,8 +749,7 @@ isce3::signal::Filter::_kaiserord(const double ripple, const double width, // order, so we have to add 1 to get the number of taps. const double numtaps = (A - 7.95) / 2.285 / (M_PI * width) + 1; - n = int(std::ceil(numtaps)); - beta = _kaiser_beta(A); + return std::make_tuple(int(std::ceil(numtaps)), _kaiser_beta(A)); } template @@ -778,7 +776,7 @@ isce3::signal::Filter::_kaiser_design(const double stopatt, double &beta, std::valarray &t) { - _kaiserord(stopatt, transition_width, n, beta); + std::tie(n, beta) = _kaiserord(stopatt, transition_width); if (force_odd_len && (n % 2 == 0)) n += 1; if (t.size() <= 0) t.resize(n); diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index 4923aa12a..e87b17a61 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -162,11 +162,9 @@ class isce3::signal::Filter { /** Determine the filter window parameters for the Kaiser window method * @param[in] ripple Upper bound for the deviation (in dB) of the magnitude of the filter's frequency response from that of the desired filter (not including frequencies in any transition intervals). * @param[in] width Width of transition region, normalized so that 1 corresponds to pi radians / sample. - * @param[out] n the length of the Kaiser window. - * @param[out] beta the beta parameter for the Kaiser window + * @return the length and the beta of the Kaiser window. */ - void _kaiserord(const double ripple, const double width, - int &n, double &beta); + std::tuple _kaiserord(const double ripple, const double width); /** Compute the Kaiser parameter `beta`, given the attenuation 'ripple` * @param[in] ripple The desired attenuation in the stopband and maximum ripple in the passband, in dB. From 8f1e9c602954997e73724b597b849cd388d4d3cd Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 7 Dec 2023 21:58:26 +0000 Subject: [PATCH 058/106] remove the reduntant functions --- cxx/isce3/signal/Crossmul.cpp | 4 ++-- cxx/isce3/signal/Filter.cpp | 35 ----------------------------------- cxx/isce3/signal/Filter.h | 10 ---------- 3 files changed, 2 insertions(+), 47 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index e66abcaae..7dd1a2c60 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -134,11 +134,11 @@ rangeCommonBandFilter(std::valarray> &refSlc, _windowParameter); // low pass filter the ref slc - rngFilter.InitCommonRangeFilter(refSlc,refSpectrum, ncols, blockLength); + rngFilter.initiateRangeFilter(refSlc,refSpectrum, ncols, blockLength); rngFilter.filter(refSlc, refSpectrum); // low pass filter the sec slc - rngFilter.InitCommonRangeFilter(secSlc,secSpectrum, ncols, blockLength); + rngFilter.initiateRangeFilter(secSlc,secSpectrum, ncols, blockLength); rngFilter.filter(secSlc, secSpectrum); // restore the original phase without the geometry phase diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 1bedc3dd9..71507096a 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -138,41 +138,6 @@ constructRangeBandpassFilter(double rangeSamplingFrequency, } } -/** - * @param[in] signal a block of data to filter - * @param[in] spectrum a block of spectrum, which is internally used for FFT computations - * @param[in] ncols number of columns of the block of data - * @param[in] nrows number of rows of the block of data -*/ -template -void -isce3::signal::Filter::InitCommonRangeFilter(std::valarray> &signal, - std::valarray> &spectrum, - size_t ncols, - size_t nrows) -{ - _signal.forwardRangeFFT(signal, spectrum, ncols, nrows); - _signal.inverseRangeFFT(spectrum, signal, ncols, nrows); -} - -/** - * @param[in] signal a block of data to filter - * @param[in] spectrum a block of spectrum, which is internally used for FFT computations - * @param[in] ncols number of columns of the block of data - * @param[in] nrows number of rows of the block of data -*/ -template -void -isce3::signal::Filter::InitCommonAzimuthFilter(std::valarray> &signal, - std::valarray> &spectrum, - size_t ncols, - size_t nrows) -{ - _signal.forwardAzimuthFFT(signal, spectrum, ncols, nrows); - _signal.inverseAzimuthFFT(spectrum, signal, ncols, nrows); -} - - /** * @param[in] rangeSamplingFrequency range sampling frequency * @param[in] subBandCenterFrequency a vector of center frequencies for each band diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index e87b17a61..6c66aaaac 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -94,11 +94,6 @@ class isce3::signal::Filter { double beta, std::valarray>& _filter1D); - /** Initialize the range FFT filter*/ - void InitCommonRangeFilter(std::valarray> &signal, - std::valarray> &spectrum, - size_t ncols, size_t nrows); - /** Construct the range common band filter*/ void constructRangeCommonbandFilter(const double rangeSamplingFrequency, const double subBandCenterFrequency, @@ -116,11 +111,6 @@ class isce3::signal::Filter { const double beta, std::valarray>& filter1D); - /** Initialize the azimuth common FFT filter*/ - void InitCommonAzimuthFilter(std::valarray> &signal, - std::valarray> &spectrum, - size_t ncols, size_t nrows); - /** Construct azimuth common band filter*/ double constructAzimuthCommonbandFilter(const std::valarray & refDoppler, const std::valarray & secDoppler, From 7c022971c5e36dc3fe281a3dc33b1e5f6ceae61c Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 7 Dec 2023 22:05:20 +0000 Subject: [PATCH 059/106] capitalize the common band --- cxx/isce3/signal/Crossmul.cpp | 4 ++-- cxx/isce3/signal/Filter.cpp | 20 ++++++++++---------- cxx/isce3/signal/Filter.h | 16 ++++++++-------- tests/cxx/isce3/signal/filter.cpp | 4 ++-- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 7dd1a2c60..985c6c359 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -125,7 +125,7 @@ rangeCommonBandFilter(std::valarray> &refSlc, // Contruct the low pass filter for this block. This filter is // common for both SLCs - rngFilter.constructRangeCommonbandFilter(_rangeSamplingFrequency, + rngFilter.constructRangeCommonBandFilter(_rangeSamplingFrequency, filterCenterFrequency, filterBandwidth, ncols, @@ -174,7 +174,7 @@ azimuthCommonBandFilter(std::valarray> &refSlc, std::string filterType = _windowType; // Construct azimuth common bandpass filter for both reference and secondary - double processedAzimuthBandwidth = azimuthFilter.constructAzimuthCommonbandFilter( + double processedAzimuthBandwidth = azimuthFilter.constructAzimuthCommonBandFilter( refDoppCentroids, secDoppCentroids, _azimuthBandwidth, _prf, _windowParameter, ncols, diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 71507096a..ffa0568bb 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -152,12 +152,12 @@ constructRangeBandpassFilter(double rangeSamplingFrequency, */ template void -isce3::signal::Filter::constructRangeCommonbandFilter(const double rangeSamplingFrequency, +isce3::signal::Filter::constructRangeCommonBandFilter(const double rangeSamplingFrequency, const double subBandCenterFrequency, const double subBandBandwidth, size_t ncols, size_t nrows, - const std::string filterType, + const std::string& filterType, const double windowParameter) { @@ -168,7 +168,7 @@ isce3::signal::Filter::constructRangeCommonbandFilter(const double rangeSampl _filter1D = std::complex(0.0,0.0); if (filterType=="kaiser"){ - constructRangeCommonbandKaiserFilter(subBandCenterFrequency, + constructRangeCommonBandKaiserFilter(subBandCenterFrequency, subBandBandwidth, rangeSamplingFrequency, fft_size, @@ -294,7 +294,7 @@ constructRangeBandpassCosine(std::valarray subBandCenterFrequencies, template void isce3::signal::Filter:: -constructRangeCommonbandKaiserFilter(const double subBandCenterFrequency, +constructRangeCommonBandKaiserFilter(const double subBandCenterFrequency, const double subBandBandwidth, const double rangeSamplingFrequency, const int fft_size, @@ -410,17 +410,17 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, template double isce3::signal::Filter:: -constructAzimuthCommonbandFilter(const std::valarray & refDoppler, +constructAzimuthCommonBandFilter(const std::valarray & refDoppler, const std::valarray & secDoppler, double bandwidth, double prf, double beta, size_t ncols, size_t nrows, - std::string filterType) + std::string& filterType) { if (filterType=="cosine"){ - return constructAzimuthCommonbandCosineFilter( + return constructAzimuthCommonBandCosineFilter( refDoppler, secDoppler, bandwidth, @@ -428,7 +428,7 @@ constructAzimuthCommonbandFilter(const std::valarray & refDoppler, ncols, nrows); } else if (filterType=="kaiser"){ - return constructAzimuthCommonbandKaiserFilter( + return constructAzimuthCommonBandKaiserFilter( refDoppler, secDoppler, bandwidth, @@ -454,7 +454,7 @@ constructAzimuthCommonbandFilter(const std::valarray & refDoppler, template double isce3::signal::Filter:: -constructAzimuthCommonbandCosineFilter(const std::valarray & refDoppler, +constructAzimuthCommonBandCosineFilter(const std::valarray & refDoppler, const std::valarray & secDoppler, double bandwidth, double prf, @@ -547,7 +547,7 @@ constructAzimuthCommonbandCosineFilter(const std::valarray & refDoppler, template double isce3::signal::Filter:: -constructAzimuthCommonbandKaiserFilter(const std::valarray & refDoppler, +constructAzimuthCommonBandKaiserFilter(const std::valarray & refDoppler, const std::valarray & secDoppler, double bandwidth, double prf, diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index 6c66aaaac..caf260c23 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -95,16 +95,16 @@ class isce3::signal::Filter { std::valarray>& _filter1D); /** Construct the range common band filter*/ - void constructRangeCommonbandFilter(const double rangeSamplingFrequency, + void constructRangeCommonBandFilter(const double rangeSamplingFrequency, const double subBandCenterFrequency, - const double subBandBandwidths, + const double subBandBandwidth, size_t ncols, size_t nrows, - const std::string filterType, + const std::string& filterType, const double windowParameter); /** Construct a kaiser common band range band-pass filter for one band*/ - void constructRangeCommonbandKaiserFilter(const double subBandCenterFrequency, + void constructRangeCommonBandKaiserFilter(const double subBandCenterFrequency, const double subBandBandwidth, const double rangeSamplingFrequency, const int fft_size, @@ -112,17 +112,17 @@ class isce3::signal::Filter { std::valarray>& filter1D); /** Construct azimuth common band filter*/ - double constructAzimuthCommonbandFilter(const std::valarray & refDoppler, + double constructAzimuthCommonBandFilter(const std::valarray & refDoppler, const std::valarray & secDoppler, double bandwidth, double prf, double beta, size_t ncols, size_t nrows, - std::string filterType); + std::string& filterType); /** Construct azimuth common band cosine filter with the doppler centroid compensation*/ - double constructAzimuthCommonbandCosineFilter(const std::valarray & refDoppler, + double constructAzimuthCommonBandCosineFilter(const std::valarray & refDoppler, const std::valarray & secDoppler, double bandwidth, double prf, @@ -131,7 +131,7 @@ class isce3::signal::Filter { size_t nrows); /** Construct azimuth common band kaiser filter with the doppler centroid compensation*/ - double constructAzimuthCommonbandKaiserFilter(const std::valarray & refDoppler, + double constructAzimuthCommonBandKaiserFilter(const std::valarray & refDoppler, const std::valarray & secDoppler, double bandwidth, double prf, diff --git a/tests/cxx/isce3/signal/filter.cpp b/tests/cxx/isce3/signal/filter.cpp index ec56e05cc..5e8096f68 100644 --- a/tests/cxx/isce3/signal/filter.cpp +++ b/tests/cxx/isce3/signal/filter.cpp @@ -14,7 +14,7 @@ #include #include -TEST(Filter, constructAzimuthCommonbandFilter) +TEST(Filter, constructAzimuthCommonBandFilter) { //This test constructs a common azimuth band filter. @@ -54,7 +54,7 @@ TEST(Filter, constructAzimuthCommonbandFilter) double commonAzimuthBandwidth = 1000.0; isce3::signal::Filter filter; - filter.constructAzimuthCommonbandCosineFilter(dop1, + filter.constructAzimuthCommonBandCosineFilter(dop1, dop2, commonAzimuthBandwidth, prf, From 984845ec9354781c239f1ae317c8c539e9f2f955 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 7 Dec 2023 22:34:33 +0000 Subject: [PATCH 060/106] change docstring --- .vscode/settings.json | 3 ++- cxx/isce3/signal/Filter.cpp | 53 +++++++++++++++++++------------------ cxx/isce3/signal/Filter.h | 30 +++++++++++++-------- 3 files changed, 48 insertions(+), 38 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index a8ddd9f34..9403e2971 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -63,6 +63,7 @@ "typeindex": "cpp", "typeinfo": "cpp", "valarray": "cpp", - "variant": "cpp" + "variant": "cpp", + "*.icc": "cpp" } } \ No newline at end of file diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index ffa0568bb..34d2faeed 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -179,7 +179,7 @@ isce3::signal::Filter::constructRangeCommonBandFilter(const double rangeSampl } //construct a block of the filter - const std::complex norm(fft_size, fft_size); + const std::complex norm(fft_size, 0.0); for (size_t line = 0; line < nrows; line++ ){ for (size_t col = 0; col < fft_size; col++ ){ _filter[line*fft_size+col] = _filter1D[col] / norm; @@ -190,7 +190,7 @@ isce3::signal::Filter::constructRangeCommonBandFilter(const double rangeSampl /** * @param[in] subBandCenterFrequencies a vector of center frequencies for each band * @param[in] subBandBandwidths a vector of bandwidths for each band - * @param[in] dt samplig rate of the signal + * @param[in] dt time interval of the signal * @param[in] fft_size length of the spectrum * @param[out] _filter1D one dimensional boxcar bandpass filter in frequency domain */ @@ -240,7 +240,7 @@ constructRangeBandpassBoxcar(std::valarray subBandCenterFrequencies, /** * @param[in] subBandCenterFrequencies a vector of center frequencies for each band * @param[in] subBandBandwidths a vector of bandwidths for each band - * @param[in] dt samplig rate of the signal + * @param[in] dt time interval of the signal * @param[in] frequency a vector of frequencies * @param[in] beta parameter for the raised cosine filter (0 <= beta <= 1) * @param[out] _filter1D one dimensional boxcar bandpass filter in frequency domain @@ -284,12 +284,12 @@ constructRangeBandpassCosine(std::valarray subBandCenterFrequencies, } /** - * @param[in] subBandCenterFrequencies a vector of center frequencies for each band - * @param[in] subBandBandwidths a vector of bandwidths for each band - * @param[in] rangeSamplingFrequency samplig rate of the signal + * @param[in] subBandCenterFrequency the center frequency, in Hz + * @param[in] subBandBandwidth the bandwidth, in Hz + * @param[in] rangeSamplingFrequency sampling rate of the signal * @param[in] fft_size length of the spectrum - * @param[in] beta parameter for the kaiser filter (normally set 2.5) - * @param[out] filter1D one dimensional boxcar bandpass filter in frequency domain + * @param[in] beta parameter for the kaiser filter + * @param[out] filter1D one dimensional kaiser filter in frequency domain */ template void @@ -303,6 +303,7 @@ constructRangeCommonBandKaiserFilter(const double subBandCenterFrequency, { if (filter1D.size() <= 0) filter1D.resize(fft_size); + filter1D = std::complex(0.0, 0.0); isce3::signal::Signal signal; signal.forwardRangeFFT(filter1D, filter1D, fft_size, 1); @@ -318,7 +319,7 @@ constructRangeCommonBandKaiserFilter(const double subBandCenterFrequency, "FFT size is less than the window size"); } - // Zero padding the filter on sides + // Zero padding the filter in the middle for (size_t ind = halfSizeOfKaiser; ind < sizeOfKaiser; ind ++) { filter1D[ind - halfSizeOfKaiser] = kaiser[ind]; } @@ -333,11 +334,11 @@ constructRangeCommonBandKaiserFilter(const double subBandCenterFrequency, /** * @param[in] subBandCenterFrequencies a vector of center frequencies for each band * @param[in] subBandBandwidths a vector of bandwidths for each band - * @param[in] dt samplig rate of the signal + * @param[in] dt time interval of the signal * @param[in] fft_size length of the spectrum * @param[in] frequency a vector of frequencies - * @param[in] beta parameter for the kaiser filter (normally set 2.5) - * @param[out] _filter1D one dimensional boxcar bandpass filter in frequency domain + * @param[in] beta parameter for the kaiser filter + * @param[out] _filter1D one dimensional kaiser filter in frequency domain */ template void @@ -534,10 +535,10 @@ constructAzimuthCommonBandCosineFilter(const std::valarray & refDoppler, } /** -* @param[in] refDoppler Doppler Centroids of the reference SLC -* @param[in] secDoppler Doppler Centroids of the secondary SLC -* @param[in] bandwidth common bandwidth in azimuth -* @param[in] prf pulse repetition frequency +* @param[in] refDoppler Doppler Centroids, in Hz, of the reference SLC w.r.t slant range axis +* @param[in] secDoppler Doppler Centroids, in Hz, of the secondary SLC w.r.t slant range axis +* @param[in] bandwidth common bandwidth in azimuth, in Hz +* @param[in] prf pulse repetition frequency, in Hz * @param[in] beta parameter for kaiser filter * @param[in] signal a block of data to filter * @param[in] spectrum of the block of data @@ -698,7 +699,7 @@ writeFilter(size_t ncols, size_t nrows) template std::tuple -isce3::signal::Filter::_kaiserord(const double ripple, const double width) +isce3::signal::Filter::_kaiserord(const double ripple, const double transition_width) { const double A = std::abs(ripple); // in case somebody is confused as to what's meant if (A < 8) { @@ -712,7 +713,7 @@ isce3::signal::Filter::_kaiserord(const double ripple, const double width) // Kaiser's formula (as given in Oppenheim and Schafer) is for the filter // order, so we have to add 1 to get the number of taps. - const double numtaps = (A - 7.95) / 2.285 / (M_PI * width) + 1; + const double numtaps = (A - 7.95) / 2.285 / (M_PI * transition_width) + 1; return std::make_tuple(int(std::ceil(numtaps)), _kaiser_beta(A)); } @@ -768,32 +769,32 @@ template void isce3::signal::Filter::_kaiser(const int n, const double beta, - std::valarray> &kaiser_window) + std::valarray> &coeffs) { const double beta0 = isce3::math::bessel_i0(beta); - if (kaiser_window.size() <= 0) kaiser_window.resize(n); + if (coeffs.size() <= 0) coeffs.resize(n); for (size_t i = 0; i < n; i++) { const double t = i - (n - 1) / 2.0; - if (std::abs(t) <= n / 2.0) kaiser_window[i] = isce3::math::bessel_i0( + if (std::abs(t) <= n / 2.0) coeffs[i] = isce3::math::bessel_i0( beta * std::sqrt(1.0 - (2 * t / (n - 1)) * (2 * t / (n - 1)))) / beta0; } } template void -isce3::signal::Filter::_lowpass2bandpass(const std::valarray> &kaiser_window, +isce3::signal::Filter::_lowpass2bandpass(const std::valarray> &low_pass_filter, const double fc, - std::valarray> &shifted_kaiser_window) + std::valarray> &band_pass_filter) { - if (shifted_kaiser_window.size() <= 0) shifted_kaiser_window.resize(kaiser_window.size()); - const int n = kaiser_window.size(); + if (band_pass_filter.size() <= 0) band_pass_filter.resize(low_pass_filter.size()); + const int n = low_pass_filter.size(); for (size_t i = 0; i < n; i++) { const double t = (i - (n - 1) / 2.0); const double phase = 2.0 * M_PI * fc * t; const std::complex ramp_phase(std::cos(phase), std::sin(phase)); - shifted_kaiser_window[i] = kaiser_window[i] * ramp_phase; + band_pass_filter[i] = low_pass_filter[i] * ramp_phase; } } diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index caf260c23..03dedc1d2 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -103,7 +103,11 @@ class isce3::signal::Filter { const std::string& filterType, const double windowParameter); - /** Construct a kaiser common band range band-pass filter for one band*/ + /** Construct a kaiser range band-pass filter for one band + * First constructs a time-domain FIR filter, then transforms to the frequency + * domain. + * Returns the frequency-domain filter coefficients. + */ void constructRangeCommonBandKaiserFilter(const double subBandCenterFrequency, const double subBandBandwidth, const double rangeSamplingFrequency, @@ -130,7 +134,11 @@ class isce3::signal::Filter { size_t ncols, size_t nrows); - /** Construct azimuth common band kaiser filter with the doppler centroid compensation*/ + /** Construct a kaiser range band-pass filter for one band + * First constructs a time-domain FIR filter, then transforms to the frequency + * domain. + * Returns the frequency-domain filter coefficients. + */ double constructAzimuthCommonBandKaiserFilter(const std::valarray & refDoppler, const std::valarray & secDoppler, double bandwidth, @@ -151,10 +159,10 @@ class isce3::signal::Filter { public: /** Determine the filter window parameters for the Kaiser window method * @param[in] ripple Upper bound for the deviation (in dB) of the magnitude of the filter's frequency response from that of the desired filter (not including frequencies in any transition intervals). - * @param[in] width Width of transition region, normalized so that 1 corresponds to pi radians / sample. + * @param[in] transition_width Width of transition region, normalized so that 1 corresponds to pi radians / sample. * @return the length and the beta of the Kaiser window. */ - std::tuple _kaiserord(const double ripple, const double width); + std::tuple _kaiserord(const double ripple, const double transition_width); /** Compute the Kaiser parameter `beta`, given the attenuation 'ripple` * @param[in] ripple The desired attenuation in the stopband and maximum ripple in the passband, in dB. @@ -189,20 +197,20 @@ class isce3::signal::Filter { /** Kaiser window with length n * @param[in] n the length of the Kaiser window. * @param[in] beta the beta parameter for the Kaiser window - * @param[out] kaiser_window time samples for Kaiser filter design method + * @param[out] coeffs the Kaiser filter coefficients */ void _kaiser(const int n, const double beta, - std::valarray> &kaiser_window); + std::valarray> &coeffs); /** Turn a low pass filter into a band pass filter by applying a phase ramp. - * @param[in] kaiser_window the Kaiser window. - * @param[in] fc the center frequency divded by sampling rate - * @param[out] shifted_kaiser_window shifted kaiser window with center frequency fc + * @param[in] low_pass_filter low pass filter + * @param[in] fc the center frequency, in Hz divded by sampling rate, in Hz + * @param[out] band_pass_filter band pass filter */ - void _lowpass2bandpass(const std::valarray> &kaiser_window, + void _lowpass2bandpass(const std::valarray> &low_pass_filter, const double fc, - std::valarray> &shifted_kaiser_window); + std::valarray> &band_pass_filter); /** Design a low pass filter having a passband shaped like a window using the Kaiser method * @param[in] bandwidth the signal bandwidth From 70362346852adcdde6ac26203a5fd992c6a016a6 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 7 Dec 2023 22:40:58 +0000 Subject: [PATCH 061/106] add the docstring --- cxx/isce3/signal/Filter.cpp | 36 ++++++++++++++++++------------------ cxx/isce3/signal/Filter.h | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 34d2faeed..53479b81d 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -47,9 +47,9 @@ initiateAzimuthFilter(std::valarray> &signal, } /** - * @param[in] rangeSamplingFrequency range sampling frequency - * @param[in] subBandCenterFrequencies a vector of center frequencies for each band - * @param[in] subBandBandwidths a vector of bandwidths for each band + * @param[in] rangeSamplingFrequency range sampling frequency, in Hz + * @param[in] subBandCenterFrequencies a vector of center frequencies for each band, in Hz + * @param[in] subBandBandwidths a vector of bandwidths for each band, in Hz * @param[in] signal a block of data to filter * @param[in] spectrum a block of spectrum, which is internally used for FFT computations * @param[in] ncols number of columns of the block of data @@ -139,9 +139,9 @@ constructRangeBandpassFilter(double rangeSamplingFrequency, } /** - * @param[in] rangeSamplingFrequency range sampling frequency - * @param[in] subBandCenterFrequency a vector of center frequencies for each band - * @param[in] subBandBandwidth a vector of bandwidths for each band + * @param[in] rangeSamplingFrequency range sampling frequency, in Hz + * @param[in] subBandCenterFrequency center frequency, in Hz + * @param[in] subBandBandwidth bandwidth, in Hz * @param[in, out] signal a block of data to filter * @param[in, out] spectrum a block of spectrum, which is internally used for FFT computations * @param[in] ncols number of columns of the block of data @@ -398,11 +398,11 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, } /** -* @param[in] refDoppler Doppler Centroids of the reference SLC -* @param[in] secDoppler Doppler Centroids of the secondary SLC -* @param[in] bandwidth common bandwidth in azimuth -* @param[in] prf pulse repetition frequency -* @param[in] beta parameter for raised cosine filter (0.25) or for the kaiser filter (2.5) +* @param[in] refDoppler Doppler Centroids, in Hz, of the reference SLC w.r.t slant range axis +* @param[in] secDoppler Doppler Centroids, in Hz, of the secondary SLC w.r.t slant range axis +* @param[in] bandwidth common bandwidth in azimuth, in Hz +* @param[in] prf pulse repetition frequency, in Hz +* @param[in] windowParameter window parameter of the filter * @param[in] signal a block of data to filter * @param[in] spectrum of the block of data * @param[in] ncols number of columns of the block of data @@ -415,7 +415,7 @@ constructAzimuthCommonBandFilter(const std::valarray & refDoppler, const std::valarray & secDoppler, double bandwidth, double prf, - double beta, + double windowParameter, size_t ncols, size_t nrows, std::string& filterType) @@ -425,7 +425,7 @@ constructAzimuthCommonBandFilter(const std::valarray & refDoppler, refDoppler, secDoppler, bandwidth, - prf, beta, + prf, windowParameter, ncols, nrows); } else if (filterType=="kaiser"){ @@ -433,7 +433,7 @@ constructAzimuthCommonBandFilter(const std::valarray & refDoppler, refDoppler, secDoppler, bandwidth, - prf, beta, + prf, windowParameter, ncols, nrows); } else{ std::cout << filterType << " filter has not been implemented" << std::endl; @@ -442,10 +442,10 @@ constructAzimuthCommonBandFilter(const std::valarray & refDoppler, } /** -* @param[in] refDoppler Doppler Centroids of the reference SLC -* @param[in] secDoppler Doppler Centroids of the secondary SLC -* @param[in] bandwidth common bandwidth in azimuth -* @param[in] prf pulse repetition frequency +* @param[in] refDoppler Doppler Centroids, in Hz, of the reference SLC w.r.t slant range axis +* @param[in] secDoppler Doppler Centroids, in Hz, of the secondary SLC w.r.t slant range axis +* @param[in] bandwidth common bandwidth in azimuth, in Hz +* @param[in] prf pulse repetition frequency, in Hz * @param[in] beta parameter for raised cosine filter * @param[in] signal a block of data to filter * @param[in] spectrum of the block of data diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index 03dedc1d2..64fe9b8f0 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -120,7 +120,7 @@ class isce3::signal::Filter { const std::valarray & secDoppler, double bandwidth, double prf, - double beta, + double windowParameter, size_t ncols, size_t nrows, std::string& filterType); From a9517b2e4f8d96b0c781723ec5851a22b6e4037e Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 7 Dec 2023 22:43:05 +0000 Subject: [PATCH 062/106] remove .vscode --- .vscode/settings.json | 69 ------------------------------------------- 1 file changed, 69 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 9403e2971..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "files.associations": { - "any": "cpp", - "array": "cpp", - "atomic": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "chrono": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "complex": "cpp", - "condition_variable": "cpp", - "csignal": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "list": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "map": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "regex": "cpp", - "set": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "new": "cpp", - "ostream": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "cinttypes": "cpp", - "typeindex": "cpp", - "typeinfo": "cpp", - "valarray": "cpp", - "variant": "cpp", - "*.icc": "cpp" - } -} \ No newline at end of file From 67b3fb03c060a970bf3f4bfe919da4105b67271f Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Fri, 8 Dec 2023 17:44:51 +0000 Subject: [PATCH 063/106] normalize the FFT transform --- cxx/isce3/signal/Filter.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 53479b81d..e2d6f2c60 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -178,11 +178,11 @@ isce3::signal::Filter::constructRangeCommonBandFilter(const double rangeSampl std::cout << filterType << "filter has not been implemented" << std::endl; } - //construct a block of the filter - const std::complex norm(fft_size, 0.0); + // construct a block of the filter, and normalize the transform to recovery the + // input signal for (size_t line = 0; line < nrows; line++ ){ for (size_t col = 0; col < fft_size; col++ ){ - _filter[line*fft_size+col] = _filter1D[col] / norm; + _filter[line*fft_size+col] = _filter1D[col] / static_cast(fft_size); } } } @@ -604,9 +604,11 @@ constructAzimuthCommonBandKaiserFilter(const std::valarray & refDoppler, meanDopCenterFreqShift += fshift; meanDopCenterFreq += fmid; - // Copy the the filter centered at fmid + // Copy the the filter centered at fmid to a block filter + // and Normalize the transform the recovery the input signal via + // dividing by fft_size for (size_t i = 0; i < filter1D.size(); ++i) { - _filter[i*ncols+j] = filter1D[i]; + _filter[i*ncols+j] = filter1D[i] / static_cast(fft_size); } } From 1c10417b1b3e161a35572aedc4aa05848adbd109 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Fri, 8 Dec 2023 19:44:33 +0000 Subject: [PATCH 064/106] fix unit tests failtures --- .vscode/settings.json | 5 +++++ cxx/isce3/signal/Crossmul.cpp | 9 +++++---- tests/cxx/isce3/signal/filter.cpp | 4 ---- tests/python/extensions/pybind/cuda/signal/crossmul.py | 2 +- tests/python/extensions/pybind/signal/crossmul.py | 2 +- 5 files changed, 12 insertions(+), 10 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..801f50371 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "*.icc": "cpp" + } +} \ No newline at end of file diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 985c6c359..ebd6e31b5 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -780,7 +780,9 @@ crossmul(isce3::io::Raster& refSlcRaster, looksObj.multilook(ifgram, ifgramMultiLooked); size_t rowNewStart = 0; - size_t nrowsMultiLooked = (linesPerBlock - halfOverlapSize) / _azimuthLooks; + size_t nrowsMultiLooked = (nblocks == 1) ? blockRowsData : blockRowsData - halfOverlapSize; + nrowsMultiLooked /= _azimuthLooks; + // The first block std::slice dataSlice = std::slice(0,ncolsMultiLooked * nrowsMultiLooked, 1); if (block > 0) { @@ -826,11 +828,10 @@ crossmul(isce3::io::Raster& refSlcRaster, coherenceRaster.setBlock(coherenceSlice, 0, rowNewStart, ncolsMultiLooked,nrowsMultiLooked); } else { - // The first block size_t rowNewStart = 0; - size_t nrowsValid = linesPerBlock - halfOverlapSize; - std::slice dataSlice = std::slice(0, nrowsValid, 1); + size_t nrowsValid = (nblocks == 1) ? blockRowsData : blockRowsData - halfOverlapSize; + std::slice dataSlice = std::slice(0, nrowsValid * ncols, 1); if (block > 0) { rowNewStart = rowStart + halfOverlapSize; if (block != (nblocks - 1)) { diff --git a/tests/cxx/isce3/signal/filter.cpp b/tests/cxx/isce3/signal/filter.cpp index 5e8096f68..f0c2863aa 100644 --- a/tests/cxx/isce3/signal/filter.cpp +++ b/tests/cxx/isce3/signal/filter.cpp @@ -39,10 +39,6 @@ TEST(Filter, constructAzimuthCommonBandFilter) std::valarray dop1(nfft); std::valarray dop2(nfft); - auto dop_lut2 = product.metadata().procInfo().dopplerCentroid('A'); - dop1 = dop_lut2.eval(0,0); - dop2 = dop1; - // get pulase repetition frequency (prf) double prf = swath.nominalAcquisitionPRF(); std::cout << "prf: " << std::setprecision(16)<< prf << std::endl; diff --git a/tests/python/extensions/pybind/cuda/signal/crossmul.py b/tests/python/extensions/pybind/cuda/signal/crossmul.py index aa83e172d..dbc702405 100644 --- a/tests/python/extensions/pybind/cuda/signal/crossmul.py +++ b/tests/python/extensions/pybind/cuda/signal/crossmul.py @@ -21,7 +21,7 @@ def common_crossmul_obj(): ''' # make SLC object and extract parameters slc_obj = SLC(hdf5file=os.path.join(iscetest.data, 'envisat.h5')) - dopp = isce3.core.avg_lut2d_to_lut1d(slc_obj.getDopplerCentroid()) + dopp = slc_obj.getDopplerCentroid() prf = slc_obj.getRadarGrid().prf crossmul = isce3.cuda.signal.Crossmul() diff --git a/tests/python/extensions/pybind/signal/crossmul.py b/tests/python/extensions/pybind/signal/crossmul.py index d5b5b6920..18ec878c9 100644 --- a/tests/python/extensions/pybind/signal/crossmul.py +++ b/tests/python/extensions/pybind/signal/crossmul.py @@ -21,7 +21,7 @@ def common_crossmul_obj(): ''' # make SLC object and extract parameters slc_obj = SLC(hdf5file=os.path.join(iscetest.data, 'envisat.h5')) - dopp = isce3.core.avg_lut2d_to_lut1d(slc_obj.getDopplerCentroid()) + dopp = slc_obj.getDopplerCentroid() prf = slc_obj.getRadarGrid().prf crossmul = isce3.signal.Crossmul() From 8a721718ddaae58ecf4021b8fc8a44cef2ec98e1 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Fri, 8 Dec 2023 23:19:34 +0000 Subject: [PATCH 065/106] chunk the filter if it is greater than the maximum kernel size --- .vscode/settings.json | 66 ++++++++++++++++++- cxx/isce3/signal/Crossmul.cpp | 36 +++++----- cxx/isce3/signal/Crossmul.h | 13 ++++ cxx/isce3/signal/Filter.cpp | 30 ++++++--- cxx/isce3/signal/Filter.h | 6 +- .../pybind_isce3/signal/Crossmul.cpp | 3 + python/packages/nisar/workflows/crossmul.py | 2 + 7 files changed, 130 insertions(+), 26 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 801f50371..32fe3b2d9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,69 @@ { "files.associations": { - "*.icc": "cpp" + "*.icc": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "set": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "valarray": "cpp", + "variant": "cpp" } } \ No newline at end of file diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index ebd6e31b5..6117a3825 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -131,7 +131,8 @@ rangeCommonBandFilter(std::valarray> &refSlc, ncols, blockLength, _windowType, - _windowParameter); + _windowParameter, + _maxFilterKernelSize); // low pass filter the ref slc rngFilter.initiateRangeFilter(refSlc,refSpectrum, ncols, blockLength); @@ -344,15 +345,17 @@ crossmul(isce3::io::Raster& refSlcRaster, throw isce3::except::LengthError(ISCE_SRCINFO(), "interferogram and coherence rasters width do not match"); - // Compute FFT size (power of 2) - size_t fft_size; - refSignal.nextPowerOfTwo(ncols, fft_size); + // Compute FFT size (power of 2) and set up the maximum range window size + size_t fft_size = isce3::fft::nextFastPower(ncols + _maxFilterKernelSize); if (fft_size > INT_MAX) throw isce3::except::LengthError(ISCE_SRCINFO(), "fft_size > INT_MAX"); if (_oversampleFactor * fft_size > INT_MAX) throw isce3::except::LengthError(ISCE_SRCINFO(), "_oversampleFactor * fft_size > INT_MAX"); + // force the multilook to be true if azimuth or range looks > 1 + _multiLookEnabled = ((_rangeLooks > 1) || (_azimuthLooks > 1)) ? true : false; + // Declare valarray for range and azimuth doppler centroids used by filter std::valarray refDoppCentroids; std::valarray secDoppCentroids; @@ -379,7 +382,7 @@ crossmul(isce3::io::Raster& refSlcRaster, _prf, _windowParameter, azimuthFilter); - std::cout << " - max kernel size = " << maxKernelSize << std::endl; + std::cout << " - max azimuth window kernel size = " << maxKernelSize << std::endl; // to ensure the overlap size is an integer multiple number of azimuth looks. maxKernelSize = (maxKernelSize + _azimuthLooks) / _azimuthLooks; @@ -590,15 +593,17 @@ crossmul(isce3::io::Raster& refSlcRaster, // For NISAR, use a standard Kaiser window in frequency domain to // compensate the windowing effects in range direction - // TODO: This function is sensor dependent - originalRangeFilter.resize(fft_size); - std::valarray subBandCenterFrequencies{0.0}; - std::valarray subBandBandwidths{_rangeSamplingFrequency}; - rangeFilter.constructRangeBandpassKaiser(subBandCenterFrequencies, - subBandBandwidths, - 1.0/_rangeSamplingFrequency, - fft_size, rangeFrequencies, 1.6, - originalRangeFilter); + // NOTE: This function is sensor dependent + if (_sensorType == "NISAR") { + originalRangeFilter.resize(fft_size); + std::valarray subBandCenterFrequencies{0.0}; + std::valarray subBandBandwidths{_rangeSamplingFrequency}; + rangeFilter.constructRangeBandpassKaiser(subBandCenterFrequencies, + subBandBandwidths, + 1.0/_rangeSamplingFrequency, + fft_size, rangeFrequencies, 1.6, + originalRangeFilter); + } // Construct the FFTW plan for both geometryIfgram and its conjugation geometryIfgramSignal.forwardRangeFFT(geometryIfgram, refSpectrum, @@ -773,13 +778,13 @@ crossmul(isce3::io::Raster& refSlcRaster, // Take looks down (summing columns) if (_multiLookEnabled) { - // mulitlook interferogram and set raster looksObj.ncols(ncols); looksObj.colsLooks(_rangeLooks); looksObj.multilook(ifgram, ifgramMultiLooked); size_t rowNewStart = 0; + // if there is only one block, the nrowsMultiLooked will be equal to blockRowsData size_t nrowsMultiLooked = (nblocks == 1) ? blockRowsData : blockRowsData - halfOverlapSize; nrowsMultiLooked /= _azimuthLooks; @@ -830,6 +835,7 @@ crossmul(isce3::io::Raster& refSlcRaster, } else { // The first block size_t rowNewStart = 0; + // if there is only one block, the nrowsValid will be equal to blockRowsData size_t nrowsValid = (nblocks == 1) ? blockRowsData : blockRowsData - halfOverlapSize; std::slice dataSlice = std::slice(0, nrowsValid * ncols, 1); if (block > 0) { diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 4a68b44dc..6bf54205b 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -8,6 +8,7 @@ #include #include #include +#include /** \brief Intereferogram generation by cross-multiplication of reference and secondary SLCs. * @@ -129,6 +130,12 @@ class isce3::signal::Crossmul { /** Set the window type */ inline void windowType(std::string windowType) { _windowType = windowType; } + /** Get sensor type*/ + inline std::string sensorType() const { return _sensorType; } + + /** Set the sensor type */ + inline void sensorType(std::string sensorType) { _sensorType = sensorType;} + /** Set common range band filtering flag */ inline void doCommonRangeBandFilter(bool doRgBandFilter) { _doCommonRangeBandFilter = doRgBandFilter; } @@ -277,6 +284,9 @@ class isce3::signal::Crossmul { // Processed azimuth bandwidth after the common band filtering in Hz double _processedAzimuthBandwidth = 0.0; + // Sensor type + std::string _sensorType = "NISAR"; + // Window type std::string _windowType = "kaiser"; @@ -303,6 +313,9 @@ class isce3::signal::Crossmul { // upsampling factor size_t _oversampleFactor = 1; + + // maximum filter kernel size over the range + int _maxFilterKernelSize = 256; }; // Get inline implementations for Crossmul diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index e2d6f2c60..9573a74e7 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -148,6 +148,7 @@ constructRangeBandpassFilter(double rangeSamplingFrequency, * @param[in] nrows number of rows of the block of data * @param[in] filterType type of the band-pass filter * @param[in] windowParameter filter parameter + * @param[in] maxFilterKernelSize maximum kernel size of the FIR filter in time domain */ template @@ -158,7 +159,8 @@ isce3::signal::Filter::constructRangeCommonBandFilter(const double rangeSampl size_t ncols, size_t nrows, const std::string& filterType, - const double windowParameter) + const double windowParameter, + const int maxFilterKernelSize) { int fft_size = ncols; @@ -173,7 +175,8 @@ isce3::signal::Filter::constructRangeCommonBandFilter(const double rangeSampl rangeSamplingFrequency, fft_size, windowParameter, - _filter1D); + _filter1D, + maxFilterKernelSize); } else { std::cout << filterType << "filter has not been implemented" << std::endl; } @@ -290,6 +293,7 @@ constructRangeBandpassCosine(std::valarray subBandCenterFrequencies, * @param[in] fft_size length of the spectrum * @param[in] beta parameter for the kaiser filter * @param[out] filter1D one dimensional kaiser filter in frequency domain + * @param[in] maxFilterKernelSize maximum kernel size of the FIR in the time domain */ template void @@ -299,7 +303,8 @@ constructRangeCommonBandKaiserFilter(const double subBandCenterFrequency, const double rangeSamplingFrequency, const int fft_size, const double beta, - std::valarray>& filter1D) + std::valarray>& filter1D, + const int maxFilterKernelSize) { if (filter1D.size() <= 0) filter1D.resize(fft_size); @@ -312,11 +317,20 @@ constructRangeCommonBandKaiserFilter(const double subBandCenterFrequency, _design_shaped_lowpass_filter(subBandBandwidth, rangeSamplingFrequency, beta, kaiser); const int sizeOfKaiser = kaiser.size(); - const int halfSizeOfKaiser = (sizeOfKaiser - 1)/2; - if (fft_size < sizeOfKaiser) { - std::cout << "FFT size is less than the window size\n"; - throw isce3::except::InvalidArgument(ISCE_SRCINFO(), - "FFT size is less than the window size"); + int halfSizeOfKaiser = (sizeOfKaiser - 1)/2; + + if (maxFilterKernelSize < sizeOfKaiser) { + std::cout << "warning: kaiser kernel size is greater than maximum kernel size, the \n"; + + // Chunk the kaiser filter when the kernel size is greater than maximum kernel size + halfSizeOfKaiser = (maxFilterKernelSize - 1)/2; + const int start = (sizeOfKaiser - maxFilterKernelSize)/2; + std::valarray> newkaiserFilter(maxFilterKernelSize); + for (size_t i = start; i < start + maxFilterKernelSize; i++) { + newkaiserFilter[i-start] = kaiser[i]; + } + kaiser.resize(maxFilterKernelSize); + kaiser = newkaiserFilter; } // Zero padding the filter in the middle diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index 64fe9b8f0..ab3fb5fc7 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -101,7 +101,8 @@ class isce3::signal::Filter { size_t ncols, size_t nrows, const std::string& filterType, - const double windowParameter); + const double windowParameter, + const int maxFilterKernelSize = 256); /** Construct a kaiser range band-pass filter for one band * First constructs a time-domain FIR filter, then transforms to the frequency @@ -113,7 +114,8 @@ class isce3::signal::Filter { const double rangeSamplingFrequency, const int fft_size, const double beta, - std::valarray>& filter1D); + std::valarray>& filter1D, + const int maxFilterKernelSize = 256); /** Construct azimuth common band filter*/ double constructAzimuthCommonBandFilter(const std::valarray & refDoppler, diff --git a/python/extensions/pybind_isce3/signal/Crossmul.cpp b/python/extensions/pybind_isce3/signal/Crossmul.cpp index e7acbf931..768b81fdc 100644 --- a/python/extensions/pybind_isce3/signal/Crossmul.cpp +++ b/python/extensions/pybind_isce3/signal/Crossmul.cpp @@ -63,6 +63,9 @@ void addbinding(py::class_ & pyCrossmul) .def_property("window_parameter", py::overload_cast<>(&Crossmul::windowParameter, py::const_), py::overload_cast(&Crossmul::windowParameter)) + .def_property("sensor_type", + py::overload_cast<>(&Crossmul::sensorType, py::const_), + py::overload_cast(&Crossmul::sensorType)) .def_property("window_type", py::overload_cast<>(&Crossmul::windowType, py::const_), py::overload_cast(&Crossmul::windowType)) diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index 200b11a04..ecf4892d5 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -80,6 +80,8 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', do_common_azimuth_band_filter # do the flatten crossmul.do_flatten = flatten + # sensor type + crossmul.sensor_type = 'RS2' crossmul.range_looks = rg_looks crossmul.az_looks = az_looks From b3ca47aab18675e12a12613d1728fb834ca7efe6 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Fri, 8 Dec 2023 23:20:14 +0000 Subject: [PATCH 066/106] remove the .vscode --- .vscode/settings.json | 69 ------------------------------------------- 1 file changed, 69 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 32fe3b2d9..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "files.associations": { - "*.icc": "cpp", - "any": "cpp", - "array": "cpp", - "atomic": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "chrono": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "complex": "cpp", - "condition_variable": "cpp", - "csignal": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "list": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "map": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "regex": "cpp", - "set": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "new": "cpp", - "ostream": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "cinttypes": "cpp", - "typeindex": "cpp", - "typeinfo": "cpp", - "valarray": "cpp", - "variant": "cpp" - } -} \ No newline at end of file From 7469d36da25b27a4138fd05539f364a839a3702d Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Fri, 8 Dec 2023 23:22:24 +0000 Subject: [PATCH 067/106] fix string --- cxx/isce3/signal/Filter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 9573a74e7..b9a7f91a9 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -320,8 +320,8 @@ constructRangeCommonBandKaiserFilter(const double subBandCenterFrequency, int halfSizeOfKaiser = (sizeOfKaiser - 1)/2; if (maxFilterKernelSize < sizeOfKaiser) { - std::cout << "warning: kaiser kernel size is greater than maximum kernel size, the \n"; - + std::cout << "warning: kaiser kernel size is greater " + << "than maximum kernel size, the filter will be chunked \n"; // Chunk the kaiser filter when the kernel size is greater than maximum kernel size halfSizeOfKaiser = (maxFilterKernelSize - 1)/2; const int start = (sizeOfKaiser - maxFilterKernelSize)/2; From 800a438d25e9adb63b3cc374d41bdf995820cda0 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 12 Dec 2023 19:10:48 +0000 Subject: [PATCH 068/106] use the maximum range kernel size with 20% spectrum overlap --- .vscode/settings.json | 68 +++++++++++++++++++++++++++++++++++ cxx/isce3/signal/Crossmul.cpp | 26 ++++++++++++-- cxx/isce3/signal/Crossmul.h | 11 +++++- cxx/isce3/signal/Filter.cpp | 15 +++----- 4 files changed, 105 insertions(+), 15 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..11b0b89d8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,68 @@ +{ + "files.associations": { + "valarray": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "set": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "variant": "cpp" + } +} \ No newline at end of file diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 6117a3825..f2b6a3ab6 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -123,6 +123,16 @@ rangeCommonBandFilter(std::valarray> &refSlc, std::string filterType = _windowType; + if (_windowType == "kaiser") { + auto [n, _] = rngFilter._kaiserord(40, 0.15 * filterBandwidth/_rangeSamplingFrequency); + if (n > _maxFilterKernelSize) { + std::cout << "Max filter length exceeded due to insufficient " + << "spectral overlap (perpendicular baseline is too large)\n"; + throw isce3::except::LengthError(ISCE_SRCINFO(), + "Max filter length exceeded due to insufficient spectral overlap (perpendicular baseline is too large)"); + } + } + // Contruct the low pass filter for this block. This filter is // common for both SLCs rngFilter.constructRangeCommonBandFilter(_rangeSamplingFrequency, @@ -345,6 +355,19 @@ crossmul(isce3::io::Raster& refSlcRaster, throw isce3::except::LengthError(ISCE_SRCINFO(), "interferogram and coherence rasters width do not match"); + // Compute the range sampling frequency in Hz using the range pixel spacing + _rangeSamplingFrequency = 1.0 / (_rangePixelSpacing*2.0/isce3::core::speed_of_light); + if (_doCommonRangeBandFilter) { + // Determine the max range filter kernel size + // 40 is the ripple, 0.15 is the default transition width + auto [n, _] = rangeFilter._kaiserord(40.0, + _minRangeSpectrumOverlapFraction * + rangeBandwidth()/_rangeSamplingFrequency * 0.15); + _maxFilterKernelSize = n; + + std::cout << " - max range filter kernel size = " << _maxFilterKernelSize << std::endl; + } + // Compute FFT size (power of 2) and set up the maximum range window size size_t fft_size = isce3::fft::nextFastPower(ncols + _maxFilterKernelSize); @@ -575,9 +598,6 @@ crossmul(isce3::io::Raster& refSlcRaster, // Retrieve the original filter to revert the range windowing effects std::valarray> originalRangeFilter; - // Compute the range sampling frequency in Hz using the range pixel spacing - _rangeSamplingFrequency = 1.0 / (_rangePixelSpacing*2.0/isce3::core::speed_of_light); - if (_doCommonAzimuthBandFilter) { // Allocate storage for azimuth spectrum refAzimuthSpectrum.resize(spectrumSize); diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 6bf54205b..4459d200a 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -314,8 +314,17 @@ class isce3::signal::Crossmul { // upsampling factor size_t _oversampleFactor = 1; + // minimum range spectrum overlap fraction between reference and secondary RSLC + double _minRangeSpectrumOverlapFraction = 0.2; + // maximum filter kernel size over the range - int _maxFilterKernelSize = 256; + // which corresponding to about 20% range spectrum overlap + // Using the function kaiserord(40,1/1.5*0.15*0.2) + // where 1/1.5 is the bandwidth/fs, 0.15 is the default transition width + // 0.2 is the minimum overlapped spetrum fraction + // between reference and secodnay RSLC, then _maxFilterKernelSize is about 225 + // NOTE: this paramer is only used when the range common band filter is enabled. + int _maxFilterKernelSize = 0; }; // Get inline implementations for Crossmul diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index b9a7f91a9..250422584 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -320,17 +320,10 @@ constructRangeCommonBandKaiserFilter(const double subBandCenterFrequency, int halfSizeOfKaiser = (sizeOfKaiser - 1)/2; if (maxFilterKernelSize < sizeOfKaiser) { - std::cout << "warning: kaiser kernel size is greater " - << "than maximum kernel size, the filter will be chunked \n"; - // Chunk the kaiser filter when the kernel size is greater than maximum kernel size - halfSizeOfKaiser = (maxFilterKernelSize - 1)/2; - const int start = (sizeOfKaiser - maxFilterKernelSize)/2; - std::valarray> newkaiserFilter(maxFilterKernelSize); - for (size_t i = start; i < start + maxFilterKernelSize; i++) { - newkaiserFilter[i-start] = kaiser[i]; - } - kaiser.resize(maxFilterKernelSize); - kaiser = newkaiserFilter; + std::cout << "error: kaiser kernel size is greater " + << "than maximum kernel size\n"; + throw isce3::except::InvalidArgument(ISCE_SRCINFO(), + "kaiser kernel size is greater than maximum kernel size"); } // Zero padding the filter in the middle From 788271633f13fef815ebc132193cde7584f81dc9 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 12 Dec 2023 19:36:53 +0000 Subject: [PATCH 069/106] chnge minors --- cxx/isce3/signal/Crossmul.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index f2b6a3ab6..b08c51bc0 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -121,8 +121,6 @@ rangeCommonBandFilter(std::valarray> &refSlc, const double filterCenterFrequency = 0.0; const double filterBandwidth = _rangeBandwidth - fabs(frequencyShift); - std::string filterType = _windowType; - if (_windowType == "kaiser") { auto [n, _] = rngFilter._kaiserord(40, 0.15 * filterBandwidth/_rangeSamplingFrequency); if (n > _maxFilterKernelSize) { @@ -157,7 +155,7 @@ rangeCommonBandFilter(std::valarray> &refSlc, refSlc *= geometryIfgram; secSlc *= geometryIfgramConj; - return (_rangeBandwidth - frequencyShift); + return filterBandwidth; } /** From 79a402be1f4e0fecdd27e2c4f255d5c642eafff9 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 12 Dec 2023 20:38:47 +0000 Subject: [PATCH 070/106] switch to pyre --- .vscode/settings.json | 2 +- cxx/isce3/geocode/GeocodeCov.cpp | 38 +++++++++++++++--------------- cxx/isce3/signal/Crossmul.cpp | 37 +++++++++++++++++++---------- cxx/isce3/signal/Filter.cpp | 40 +++++++++++++++++++++++--------- 4 files changed, 74 insertions(+), 43 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 11b0b89d8..a8ddd9f34 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,5 @@ { "files.associations": { - "valarray": "cpp", "any": "cpp", "array": "cpp", "atomic": "cpp", @@ -63,6 +62,7 @@ "cinttypes": "cpp", "typeindex": "cpp", "typeinfo": "cpp", + "valarray": "cpp", "variant": "cpp" } } \ No newline at end of file diff --git a/cxx/isce3/geocode/GeocodeCov.cpp b/cxx/isce3/geocode/GeocodeCov.cpp index cd3c4d1ff..1b55f70c7 100644 --- a/cxx/isce3/geocode/GeocodeCov.cpp +++ b/cxx/isce3/geocode/GeocodeCov.cpp @@ -181,7 +181,7 @@ void Geocode::geocode(const isce3::product::RadarGridParameters& radar_grid, az_time_correction, slant_range_correction, input_rtc, output_rtc, input_layover_shadow_mask_raster, sub_swaths, - out_valid_samples_sub_swath_mask, + out_valid_samples_sub_swath_mask, geocode_memory_mode, min_block_size, max_block_size, dem_interp_method); else if (flag_run_geocode_interp) @@ -418,11 +418,11 @@ void Geocode::geocodeInterp( if (out_geo_rtc_gamma0_to_sigma0 != nullptr) { std::string vsimem_ref = ( "/vsimem/" + getTempString("geocode_cov_areaproj_rtc_sigma0")); - rtc_raster_sigma0_unique_ptr = + rtc_raster_sigma0_unique_ptr = std::make_unique( vsimem_ref, radar_grid.width(), radar_grid.length(), 1, GDT_Float32, "ENVI"); - rtc_sigma0_raster = + rtc_sigma0_raster = rtc_raster_sigma0_unique_ptr.get(); } @@ -469,7 +469,7 @@ void Geocode::geocodeInterp( block_length = geogrid.length(); } else { - if (geocode_memory_mode == + if (geocode_memory_mode == isce3::core::GeocodeMemoryMode::BlocksGeogridAndRadarGrid) { warning << "WARNING the geocode memory mode" << " BlocksGeogridAndRadarGrid is not available" @@ -481,7 +481,7 @@ void Geocode::geocodeInterp( isce3::core::getBlockProcessingParametersY( geogrid.length(), geogrid.width(), nbands, sizeof(T), &info, &block_length, &nBlocks, min_block_size, max_block_size); - } + } info << "number of blocks: " << nBlocks << pyre::journal::newline; info << "block length: " << block_length << pyre::journal::newline; @@ -762,7 +762,7 @@ void Geocode::geocodeInterp( geoBlockLength, geogrid.width()); out_valid_samples_sub_swath_mask_array.fill(0); } - + _interpolate(rdrDataBlock, geoDataBlock, radarX, radarY, rdrBlockWidth, rdrBlockLength, azimuthFirstLine, rangeFirstPixel, interp.get(), radar_grid, @@ -927,7 +927,7 @@ inline void Geocode::_interpolate( // set NaN values according to T_out, i.e. real (NaN) // or complex (NaN, NaN) using T_out_real = typename isce3::real::type; - geoDataBlock(i, j) *= + geoDataBlock(i, j) *= std::numeric_limits::quiet_NaN(); if (flag_apply_rtc && out_geo_rtc != nullptr) { out_geo_rtc_array(i, j) = @@ -947,7 +947,7 @@ inline void Geocode::_interpolate( if (yy == 0 && xx == 0) { sample_sub_swath_center = sample_sub_swath; } - + } if (flag_skip) { break; @@ -961,10 +961,10 @@ inline void Geocode::_interpolate( out_valid_samples_sub_swath_mask_array(i, j) = sample_sub_swath_center; } - /* + /* check within the interpolation kernel (approximated by `interp_margin`) if any of the samples is marked as shadow or layover-and-shadow - in which case we skip to the next position, i.e., we "break" the + in which case we skip to the next position, i.e., we "break" the 2 inner for-loop bellow (vars: yy and xx) and "continue" from the parent for-loop (var: kk) above. */ @@ -1886,11 +1886,11 @@ void Geocode::geocodeAreaProj( if (out_geo_rtc_gamma0_to_sigma0 != nullptr) { std::string vsimem_ref = ( "/vsimem/" + getTempString("geocode_cov_areaproj_rtc_sigma0")); - rtc_raster_sigma0_unique_ptr = + rtc_raster_sigma0_unique_ptr = std::make_unique( vsimem_ref, radar_grid.width(), radar_grid.length(), 1, GDT_Float32, "ENVI"); - rtc_sigma0_raster = + rtc_sigma0_raster = rtc_raster_sigma0_unique_ptr.get(); } @@ -2044,7 +2044,7 @@ void Geocode::geocodeAreaProj( } else { isce3::core::getBlockProcessingParametersXY( imax, jmax, nbands + nbands_off_diag_terms, sizeof(T_out), - &info, &block_size_with_upsampling_y, &nblocks_y, + &info, &block_size_with_upsampling_y, &nblocks_y, &block_size_with_upsampling_x, &nblocks_x, min_block_size, max_block_size, geogrid_upsampling); block_size_x = block_size_with_upsampling_x / geogrid_upsampling; @@ -2085,7 +2085,7 @@ void Geocode::geocodeAreaProj( rtc_min_value, 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, + input_layover_shadow_mask, sub_swaths, out_valid_samples_sub_swath_mask, geocode_memory_mode, min_block_size, max_block_size, info); } @@ -2291,7 +2291,7 @@ void Geocode::_runBlock( isce3::io::Raster& dem_raster, isce3::io::Raster* out_off_diag_terms, isce3::io::Raster* out_geo_rdr, isce3::io::Raster* out_geo_dem, isce3::io::Raster* out_geo_nlooks, isce3::io::Raster* out_geo_rtc, - isce3::io::Raster* out_geo_rtc_gamma0_to_sigma0, + isce3::io::Raster* out_geo_rtc_gamma0_to_sigma0, isce3::core::ProjectionBase* proj, bool flag_apply_rtc, isce3::io::Raster* rtc_raster, isce3::io::Raster* rtc_sigma0_raster, @@ -2671,7 +2671,7 @@ void Geocode::_runBlock( this_block_size_y, this_block_size_x)); nan_t_out *= std::numeric_limits::quiet_NaN(); - + for (int band = 0; band < nbands; ++band) geoDataBlock[band]->fill(nan_t_out); @@ -3013,7 +3013,7 @@ void Geocode::_runBlock( also need to add `offset_x` and `offset_y` that represent the offsets in X- and Y- directions over the radar-grid coordinates. - in which case we skip to the next position, i.e., we "break" the + in which case we skip to the next position, i.e., we "break" the 2 inner for-loop bellow (vars: yy and xx) and "continue" from the parent for-loop (var: kk) above. */ @@ -3032,7 +3032,7 @@ void Geocode::_runBlock( short sample_sub_swath = 1; if (sub_swaths != nullptr) { sub_swaths->getSampleSubSwath(y, x); - + // Check if radar sample is invalid (radar-grid // single-block) if (sub_swaths != nullptr && @@ -3368,7 +3368,7 @@ std::string _get_geocode_memory_mode_str( } template -void Geocode::_print_parameters(pyre::journal::info_t& channel, +void Geocode::_print_parameters(pyre::journal::info_t& channel, isce3::core::GeocodeMemoryMode& geocode_memory_mode, const long long min_block_size, const long long max_block_size) { diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index b08c51bc0..f37cb93ea 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -3,6 +3,7 @@ #include "Filter.h" #include "Looks.h" #include "Signal.h" +#include /** * Compute the frequency response due to a subpixel shift introduced by @@ -89,6 +90,8 @@ rangeCommonBandFilter(std::valarray> &refSlc, size_t blockLength, size_t ncols) { + pyre::journal::debug_t debug("isce.signal.Crossmul.rangeCommonBandFilter"); + // size of the arrays size_t vectorLength = refSlc.size(); @@ -112,8 +115,8 @@ rangeCommonBandFilter(std::valarray> &refSlc, ncols, frequencyShift); - std::cout << " - rangeFrequencyShift (MHz): "<< frequencyShift/1e6 << std::endl; - std::cout << " - range bandwidth (MHz): " << _rangeBandwidth/1e6 << std::endl; + debug << "rangeFrequencyShift (MHz): "<< frequencyShift/1e6 << pyre::journal::endl; + debug << "range bandwidth (MHz): " << _rangeBandwidth/1e6 << pyre::journal::endl; // Since the spectrum of the ref and sec SLCs are already aligned, // we design the low-pass filter as a band-pass at zero frequency with @@ -124,8 +127,11 @@ rangeCommonBandFilter(std::valarray> &refSlc, if (_windowType == "kaiser") { auto [n, _] = rngFilter._kaiserord(40, 0.15 * filterBandwidth/_rangeSamplingFrequency); if (n > _maxFilterKernelSize) { - std::cout << "Max filter length exceeded due to insufficient " - << "spectral overlap (perpendicular baseline is too large)\n"; + pyre::journal::error_t err( + "isce.signal.Crossmul.rangeCommonBandFilter"); + err << "Max filter length exceeded due to insufficient " + << "spectral overlap (perpendicular baseline is too large)" + << pyre::journal::endl; throw isce3::except::LengthError(ISCE_SRCINFO(), "Max filter length exceeded due to insufficient spectral overlap (perpendicular baseline is too large)"); } @@ -236,7 +242,10 @@ isce3::signal::Crossmul::_maximum_kernel_size(std::valarray &refDopplerC // get width at sample rate of filter. const double tw = transition_width * bw; if ((bw + tw / 2.0) > 1.0) { - std::cout << "Passband + transition cannot exceed Nyquist\n"; + pyre::journal::error_t err( + "isce.signal.Crossmul._maximum_kernel_size"); + err << "Passband + transition cannot exceed Nyquis " + << pyre::journal::endl; throw isce3::except::InvalidArgument(ISCE_SRCINFO(), "Passband + transition cannot exceed Nyquist"); } @@ -325,6 +334,9 @@ crossmul(isce3::io::Raster& refSlcRaster, isce3::io::Raster* aziOffsetRaster) { + pyre::journal::info_t info("isce.signal.Crossmul.crossmul"); + pyre::journal::debug_t debug("isce.signal.Crossmul.crossmul"); + // number of threads size_t nthreads = omp_thread_count(); @@ -363,7 +375,7 @@ crossmul(isce3::io::Raster& refSlcRaster, rangeBandwidth()/_rangeSamplingFrequency * 0.15); _maxFilterKernelSize = n; - std::cout << " - max range filter kernel size = " << _maxFilterKernelSize << std::endl; + debug << "max range filter kernel size: " << _maxFilterKernelSize << pyre::journal::endl; } // Compute FFT size (power of 2) and set up the maximum range window size @@ -390,7 +402,7 @@ crossmul(isce3::io::Raster& refSlcRaster, refDoppCentroids.resize(fft_size); refDoppCentroids = 0.0; secDoppCentroids.resize(fft_size); secDoppCentroids = 0.0; - std::cout << " - compute the doppler centroids\n"; + info << "determine the max azimuth kernel size" << pyre::journal::newline; _compute_DoppCentroids(_refDoppler, _secDoppler, rngOffsetRaster, aziOffsetRaster, @@ -403,7 +415,7 @@ crossmul(isce3::io::Raster& refSlcRaster, _prf, _windowParameter, azimuthFilter); - std::cout << " - max azimuth window kernel size = " << maxKernelSize << std::endl; + debug << "max azimuth window kernel size: " << _maxFilterKernelSize << pyre::journal::endl; // to ensure the overlap size is an integer multiple number of azimuth looks. maxKernelSize = (maxKernelSize + _azimuthLooks) / _azimuthLooks; @@ -646,9 +658,11 @@ crossmul(isce3::io::Raster& refSlcRaster, } // loop over all blocks - std::cout << "nblocks : " << nblocks << std::endl; + std::cout << "nblocks: " << nblocks << std::endl; + info << "nblocks: " << nblocks << pyre::journal::newline; for (size_t block = 0; block < nblocks; ++block) { std::cout << "block: " << block << std::endl; + info << "block: " << block << pyre::journal::newline; // start row for this block const auto rowStart = block * (linesPerBlock - overlapSize); @@ -694,9 +708,8 @@ crossmul(isce3::io::Raster& refSlcRaster, // common range band-pass filtering if (_doCommonRangeBandFilter) { // Some diagnostic messages to make sure everything has been configured - // TODO use journal instead of cout - std::cout << " - range pixel spacing (m): " << _rangePixelSpacing << std::endl; - std::cout << " - wavelength (m): " << _wavelength << std::endl; + debug << "range pixel spacing (m): " << _rangePixelSpacing << pyre::journal::endl; + debug << "wavelength (m): " << _wavelength << pyre::journal::endl; refWindowSignal.forward(refSlc, refSpectrum); secWindowSignal.forward(secSlc, secSpectrum); diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 250422584..b0569542d 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -6,6 +6,7 @@ // #include "Filter.h" +#include /** * @param[in] signal a block of data to filter @@ -178,7 +179,10 @@ isce3::signal::Filter::constructRangeCommonBandFilter(const double rangeSampl _filter1D, maxFilterKernelSize); } else { - std::cout << filterType << "filter has not been implemented" << std::endl; + pyre::journal::error_t err( + "isce.signal.Filter.constructRangeCommonBandFilter"); + err << filterType <<" filter has not been implemented" + << pyre::journal::endl; } // construct a block of the filter, and normalize the transform to recovery the @@ -320,8 +324,11 @@ constructRangeCommonBandKaiserFilter(const double subBandCenterFrequency, int halfSizeOfKaiser = (sizeOfKaiser - 1)/2; if (maxFilterKernelSize < sizeOfKaiser) { - std::cout << "error: kaiser kernel size is greater " - << "than maximum kernel size\n"; + pyre::journal::error_t err( + "isce.signal.Filter.constructRangeCommonBandKaiserFilter"); + err << "kaiser kernel size " << sizeOfKaiser <<" is greater han maximum kernel size" + << maxFilterKernelSize + << pyre::journal::endl; throw isce3::except::InvalidArgument(ISCE_SRCINFO(), "kaiser kernel size is greater than maximum kernel size"); } @@ -563,6 +570,8 @@ constructAzimuthCommonBandKaiserFilter(const std::valarray & refDoppler, size_t ncols, size_t nrows) { + pyre::journal::debug_t debug("isce.signal.Filter.constructAzimuthCommonBandKaiserFilter"); + _filter.resize(ncols*nrows); _filter = std::complex(0.0, 0.0); int fft_size = nrows; @@ -592,10 +601,14 @@ constructAzimuthCommonBandKaiserFilter(const std::valarray & refDoppler, const int sizeOfKaiser = kaiser.size(); const int halfSizeOfKaiser = (sizeOfKaiser - 1)/2; if (fft_size < sizeOfKaiser) { - std::cout << "FFT size is less than the window size\n"; - throw isce3::except::InvalidArgument(ISCE_SRCINFO(), + pyre::journal::error_t err( + "isce.signal.Filter.constructAzimuthCommonBandKaiserFilter"); + err << "FFT size is less than the window size " + << pyre::journal::endl; + throw isce3::except::LengthError(ISCE_SRCINFO(), "FFT size is less than the window size"); } + // Zero padding the filter in the middle filter1D = std::complex(0.0, 0.0); for (size_t ind = halfSizeOfKaiser; ind < sizeOfKaiser; ind ++) { @@ -622,8 +635,8 @@ constructAzimuthCommonBandKaiserFilter(const std::valarray & refDoppler, meanDopCenterFreq /= ncols; meanDopCenterFreqShift /= ncols; - std::cout << " - mean doppler center freq (Hz):" << meanDopCenterFreq << std::endl; - std::cout << " - mean doppler center freq shift (Hz):" << meanDopCenterFreqShift << std::endl; + debug << " - mean doppler center freq (Hz):" << meanDopCenterFreq << pyre::journal::endl; + debug << " - mean doppler center freq shift (Hz):" << meanDopCenterFreqShift << pyre::journal::endl; return (bandwidth - meanDopCenterFreqShift); } @@ -713,9 +726,11 @@ isce3::signal::Filter::_kaiserord(const double ripple, const double transitio const double A = std::abs(ripple); // in case somebody is confused as to what's meant if (A < 8) { // Formula for N is not valid in this range. - std::cout << "Requested maximum ripple attentuation " << A - << " is too small for the Kaiser formula.\n"; - + pyre::journal::error_t err( + "isce.signal.Filter._kaiserord"); + err << "Requested maximum ripple attentuation " << A + << " is too small for the Kaiser formula." + << pyre::journal::endl; throw isce3::except::InvalidArgument(ISCE_SRCINFO(), "Requested maximum ripple attentuation is too small for the Kaiser formula."); } @@ -825,7 +840,10 @@ isce3::signal::Filter::_design_shaped_lowpass_filter(const double bandwidth, const double tw = transition_width * bw; if ((bw + tw / 2.0) > 1.0) { - std::cout << "Passband + transition cannot exceed Nyquist\n"; + pyre::journal::error_t err( + "isce.signal.Filter._design_shaped_lowpass_filter"); + err << "Passband + transition cannot exceed Nyquist" + << pyre::journal::endl; throw isce3::except::InvalidArgument(ISCE_SRCINFO(), "Passband + transition cannot exceed Nyquist"); } From 68ecd4e2bd51bd20b2e3a7425b7a0021f45f3021 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 12 Dec 2023 20:39:57 +0000 Subject: [PATCH 071/106] remove .vscode --- .vscode/settings.json | 68 ------------------------------------------- 1 file changed, 68 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index a8ddd9f34..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "files.associations": { - "any": "cpp", - "array": "cpp", - "atomic": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "chrono": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "complex": "cpp", - "condition_variable": "cpp", - "csignal": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "list": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "map": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "regex": "cpp", - "set": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "new": "cpp", - "ostream": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "cinttypes": "cpp", - "typeindex": "cpp", - "typeinfo": "cpp", - "valarray": "cpp", - "variant": "cpp" - } -} \ No newline at end of file From def920d257915851073b52780f3cc100680438b7 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 12 Dec 2023 21:24:25 +0000 Subject: [PATCH 072/106] fix LY comments --- cxx/isce3/signal/Crossmul.cpp | 30 ++++++++++++++++-------------- cxx/isce3/signal/Crossmul.h | 11 +++++------ cxx/isce3/signal/Crossmul.icc | 21 +++++++++------------ cxx/isce3/signal/Filter.cpp | 1 + 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index f37cb93ea..4d858748c 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -100,20 +100,19 @@ rangeCommonBandFilter(std::valarray> &refSlc, // (slope-dependent) wavenumber. This shift in frequency domain is // achieved by removing/adding the geometrical phase (representing topography) // from/to reference and secondary SLCs in time domain. - refSlc *= geometryIfgramConj; - secSlc *= geometryIfgram; - - // range frequency shift, in Hz - double frequencyShift = 0.0; + #pragma omp parallel for + for (size_t i = 0; i < refSlc.size(); i++) { + refSlc[i] *= geometryIfgramConj[i]; + secSlc[i] *= geometryIfgram[i]; + } - // determine the frequency shift based on the power spectral density of + // determine the frequency shift, in Hz based on the power spectral density of // the geometrical interferometric phase using an empirical approach - rangeFrequencyShift(refSpectrum, - secSpectrum, - rangeFrequencies, - blockLength, - ncols, - frequencyShift); + double frequencyShift = computeRangeFrequencyShift(refSpectrum, + secSpectrum, + rangeFrequencies, + blockLength, + ncols); debug << "rangeFrequencyShift (MHz): "<< frequencyShift/1e6 << pyre::journal::endl; debug << "range bandwidth (MHz): " << _rangeBandwidth/1e6 << pyre::journal::endl; @@ -158,8 +157,11 @@ rangeCommonBandFilter(std::valarray> &refSlc, // restore the original phase without the geometry phase // in case other steps will use the original phase - refSlc *= geometryIfgram; - secSlc *= geometryIfgramConj; + #pragma omp parallel for + for (size_t i = 0; i < refSlc.size(); i++) { + refSlc[i] *= geometryIfgram[i]; + secSlc[i] *= geometryIfgramConj[i]; + } return filterBandwidth; } diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 4459d200a..1bc835c5f 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -115,16 +115,16 @@ class isce3::signal::Crossmul { inline double processedAzimuthBandwidth() const { return _processedAzimuthBandwidth; } - /** Set window parameter for the azimuth common band filter + /** Set window parameter for the common band filter The meaning of this parameter depends on the `window_type`. For a raised-cosine window, it is the pedestal height of the window. For a Kaiser window, it is the beta parameter.*/ inline void windowParameter(double windowParameter) { _windowParameter = windowParameter; } - /** Get window parameter for the azimuth common band filter */ + /** Get window parameter for the common band filter */ inline double windowParameter() const { return _windowParameter; } - /** Get window type for the azimuth common band filter */ + /** Get window type for the common band filter */ inline std::string windowType() const { return _windowType; } /** Set the window type */ @@ -184,12 +184,11 @@ class isce3::signal::Crossmul { inline bool multiLookEnabled() const { return _multiLookEnabled; } /** Compute the avergae frequency shift in range direction between two SLCs*/ - inline void rangeFrequencyShift(std::valarray> &refAvgSpectrum, + inline double computeRangeFrequencyShift(std::valarray> &refAvgSpectrum, std::valarray> &secAvgSpectrum, std::valarray &rangeFrequencies, size_t linesPerBlockData, - size_t fft_size, - double &frequencyShift); + size_t fft_size); /** estimate the index of the maximum of a vector of data */ inline void getPeakIndex(std::valarray data, diff --git a/cxx/isce3/signal/Crossmul.icc b/cxx/isce3/signal/Crossmul.icc index e38aad257..f092036ae 100644 --- a/cxx/isce3/signal/Crossmul.icc +++ b/cxx/isce3/signal/Crossmul.icc @@ -65,19 +65,18 @@ azimuthLooks(int azimuthLooks) } /** @param[in] refSpectrum the spectrum of a block of a complex data -@param[in] secSpectrum the spectrum of a block of complex data -@param[in] rangeFrequencies the frequencies in range direction -@param[in] linesPerBlock number of rows in refSpectrum and secSpectrum -@param[in] fft_size number of columns in refSpectrum and secSpectrum -@param[out] estimated frequency shift between refSpectrum and secSpectrum + @param[in] secSpectrum the spectrum of a block of complex data + @param[in] rangeFrequencies the frequencies in range direction + @param[in] linesPerBlock number of rows in refSpectrum and secSpectrum + @param[in] fft_size number of columns in refSpectrum and secSpectrum + @return estimated frequency shift between refSpectrum and secSpectrum */ -void isce3::signal::Crossmul:: -rangeFrequencyShift(std::valarray> &refSpectrum, +double isce3::signal::Crossmul:: +computeRangeFrequencyShift(std::valarray> &refSpectrum, std::valarray> &secSpectrum, std::valarray &rangeFrequencies, size_t linesPerBlock, - size_t fft_size, - double &frequencyShift) + size_t fft_size) { std::valarray refAvgSpectrum(fft_size); @@ -108,8 +107,6 @@ rangeFrequencyShift(std::valarray> &refSpectrum, // get the index of the max of secAvgSpectrum getPeakIndex(secAvgSpectrum, idx2); - //std::cout << "idx1, idx2, columns: "<< idx1 << " , " << idx2 << ", " << fft_size <> &refSpectrum, // frequency shift is the difference of the two peaks // i.e., two times of the offset of the one peak - frequencyShift = 2.0 * rangeFrequencies[idx]; + return 2.0 * rangeFrequencies[idx]; } /**@param[in] data a vector to be evaluated for the index of its maximum diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index b0569542d..1420f1779 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -188,6 +188,7 @@ isce3::signal::Filter::constructRangeCommonBandFilter(const double rangeSampl // construct a block of the filter, and normalize the transform to recovery the // input signal for (size_t line = 0; line < nrows; line++ ){ + #pragma omp parallel for for (size_t col = 0; col < fft_size; col++ ){ _filter[line*fft_size+col] = _filter1D[col] / static_cast(fft_size); } From 18a1991ab45e1c4447858589dd27cfafffb8632b Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 12 Dec 2023 21:27:40 +0000 Subject: [PATCH 073/106] formats --- cxx/isce3/signal/Crossmul.cpp | 1 - cxx/isce3/signal/Crossmul.h | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 4d858748c..78c14ba49 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -376,7 +376,6 @@ crossmul(isce3::io::Raster& refSlcRaster, _minRangeSpectrumOverlapFraction * rangeBandwidth()/_rangeSamplingFrequency * 0.15); _maxFilterKernelSize = n; - debug << "max range filter kernel size: " << _maxFilterKernelSize << pyre::journal::endl; } diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 1bc835c5f..1fd666af5 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -194,8 +194,7 @@ class isce3::signal::Crossmul { inline void getPeakIndex(std::valarray data, size_t &peakIndex); - /** Range common band filtering block by block @insar2007product - */ + /** Range common band filtering block by block @insar2007product */ double rangeCommonBandFilter(std::valarray> &refSlc, std::valarray> &secSlc, const std::valarray> &geometryIfgram, From 52e0b1af9064e751a45402384c88c2c205828f71 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 12 Dec 2023 22:37:07 +0000 Subject: [PATCH 074/106] add kaiser filter unit test --- .vscode/settings.json | 68 +++++++++++++++++++++++++++++++ cxx/isce3/signal/Crossmul.cpp | 1 - tests/cxx/isce3/signal/filter.cpp | 25 +++++++++++- 3 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..a8ddd9f34 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,68 @@ +{ + "files.associations": { + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "set": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "valarray": "cpp", + "variant": "cpp" + } +} \ No newline at end of file diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 78c14ba49..234d739eb 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -335,7 +335,6 @@ crossmul(isce3::io::Raster& refSlcRaster, isce3::io::Raster* rngOffsetRaster, isce3::io::Raster* aziOffsetRaster) { - pyre::journal::info_t info("isce.signal.Crossmul.crossmul"); pyre::journal::debug_t debug("isce.signal.Crossmul.crossmul"); diff --git a/tests/cxx/isce3/signal/filter.cpp b/tests/cxx/isce3/signal/filter.cpp index f0c2863aa..8bee457da 100644 --- a/tests/cxx/isce3/signal/filter.cpp +++ b/tests/cxx/isce3/signal/filter.cpp @@ -57,7 +57,6 @@ TEST(Filter, constructAzimuthCommonBandFilter) beta, ncols, blockRows); filter.writeFilter(ncols, blockRows); - } TEST(Filter, constructBoxcarRangeBandpassFilter) @@ -117,6 +116,30 @@ TEST(Filter, constructBoxcarRangeBandpassFilter) } +TEST(Filter, constructRangeCommonBandKaiserFilter) +{ + //This test constructs a kaiser common band range band-pass FIR filter. + int fft_size = 256; + std::valarray> kaiser; + + double subBandCenterFrequency = 0.0; + double subBandBandwidth = 2.0e6; + // Assume range sampling frequency equals bandwidth for this test + double rangeSamplingFrequency = 1.2 * subBandBandwidth; + + isce3::signal::Filter filter; + filter.constructRangeCommonBandKaiserFilter(subBandCenterFrequency, + subBandBandwidth, + rangeSamplingFrequency, + fft_size, + 1.6, + kaiser); + + ASSERT_LT(std::abs(std::abs(kaiser[0]) - 0.768964), 1.0e-6); + ASSERT_LT(std::abs(std::abs(kaiser[127]) - 0.234426), 1.0e-6); + ASSERT_LT(std::abs(std::abs(kaiser[255]) - 0.768879), 1.0e-6); +} + int main(int argc, char * argv[]) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); From 8b4d211576d3722ba7ddbd5d117fad075c187f4b Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 12 Dec 2023 22:37:30 +0000 Subject: [PATCH 075/106] remove .vscode --- .vscode/settings.json | 68 ------------------------------------------- 1 file changed, 68 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index a8ddd9f34..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "files.associations": { - "any": "cpp", - "array": "cpp", - "atomic": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "chrono": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "complex": "cpp", - "condition_variable": "cpp", - "csignal": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "list": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "map": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "regex": "cpp", - "set": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "new": "cpp", - "ostream": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "cinttypes": "cpp", - "typeindex": "cpp", - "typeinfo": "cpp", - "valarray": "cpp", - "variant": "cpp" - } -} \ No newline at end of file From 9e74b2296521022b7c5802ad724bca63773acef0 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 12 Dec 2023 22:53:59 +0000 Subject: [PATCH 076/106] formats --- tests/cxx/isce3/signal/filter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cxx/isce3/signal/filter.cpp b/tests/cxx/isce3/signal/filter.cpp index 8bee457da..1967a260c 100644 --- a/tests/cxx/isce3/signal/filter.cpp +++ b/tests/cxx/isce3/signal/filter.cpp @@ -124,7 +124,7 @@ TEST(Filter, constructRangeCommonBandKaiserFilter) double subBandCenterFrequency = 0.0; double subBandBandwidth = 2.0e6; - // Assume range sampling frequency equals bandwidth for this test + // Assume range sampling frequency equals 1.2 times bandwidth for this test double rangeSamplingFrequency = 1.2 * subBandBandwidth; isce3::signal::Filter filter; From 2314779f775101c5138fdc0bded4b92cf36222e3 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 13 Dec 2023 04:32:42 +0000 Subject: [PATCH 077/106] improve speedup --- cxx/isce3/signal/Crossmul.cpp | 41 +++++++++++++++++------------------ cxx/isce3/signal/Crossmul.h | 4 ++-- cxx/isce3/signal/Filter.cpp | 11 +++++++--- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 234d739eb..f66143182 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -100,11 +100,8 @@ rangeCommonBandFilter(std::valarray> &refSlc, // (slope-dependent) wavenumber. This shift in frequency domain is // achieved by removing/adding the geometrical phase (representing topography) // from/to reference and secondary SLCs in time domain. - #pragma omp parallel for - for (size_t i = 0; i < refSlc.size(); i++) { - refSlc[i] *= geometryIfgramConj[i]; - secSlc[i] *= geometryIfgram[i]; - } + refSlc *= geometryIfgramConj; + secSlc *= geometryIfgram; // determine the frequency shift, in Hz based on the power spectral density of // the geometrical interferometric phase using an empirical approach @@ -157,11 +154,8 @@ rangeCommonBandFilter(std::valarray> &refSlc, // restore the original phase without the geometry phase // in case other steps will use the original phase - #pragma omp parallel for - for (size_t i = 0; i < refSlc.size(); i++) { - refSlc[i] *= geometryIfgram[i]; - secSlc[i] *= geometryIfgramConj[i]; - } + refSlc *= geometryIfgram; + secSlc *= geometryIfgramConj; return filterBandwidth; } @@ -218,7 +212,7 @@ azimuthCommonBandFilter(std::valarray> &refSlc, */ int -isce3::signal::Crossmul::_maximum_kernel_size(std::valarray &refDopplerCentroids, +isce3::signal::Crossmul::_computeMaxAzimuthFilterKernelSize(std::valarray &refDopplerCentroids, std::valarray &secDopplerCentroids, const double bandwidth, const double prf, @@ -268,7 +262,7 @@ isce3::signal::Crossmul::_maximum_kernel_size(std::valarray &refDopplerC * @param[out] secDopplerCentroids blockLength number of rows */ void -isce3::signal::Crossmul::_compute_DoppCentroids(const isce3::core::LUT2d & refDoppler, +isce3::signal::Crossmul::_computeDoppCentroids(const isce3::core::LUT2d & refDoppler, const isce3::core::LUT2d & secDoppler, isce3::io::Raster* rngOffsetRaster, isce3::io::Raster* aziOffsetRaster, @@ -287,19 +281,24 @@ isce3::signal::Crossmul::_compute_DoppCentroids(const isce3::core::LUT2d secDopplerCentroids = 0.0; } - std::valarray rangeOffsets(ncols); - std::valarray azimuthOffsets(ncols); std::valarray validNumbers(ncols); validNumbers = 0; // Compute the doppler centroids for the reference and secondary images + #pragma omp parallel for for (size_t row = 0; row < nrows; row++) { - rngOffsetRaster->getLine(rangeOffsets, row); - aziOffsetRaster->getLine(azimuthOffsets, row); + // Private variables for each thread + std::valarray rangeOffsets(ncols); + std::valarray azimuthOffsets(ncols); + + // Read the data thread by thread + #pragma omp critical + { + rngOffsetRaster->getLine(rangeOffsets, row); + aziOffsetRaster->getLine(azimuthOffsets, row); + } - #pragma omp parallel for for (size_t col = 0; col < ncols; col++) { - // Convert the line/pixel to range doppler coordinates double refX = col * rangePixelSpacing() + refStartRange(); double refY = row / prf() + refStartAzimuthTime(); @@ -403,20 +402,20 @@ crossmul(isce3::io::Raster& refSlcRaster, secDoppCentroids.resize(fft_size); secDoppCentroids = 0.0; info << "determine the max azimuth kernel size" << pyre::journal::newline; - _compute_DoppCentroids(_refDoppler, _secDoppler, + _computeDoppCentroids(_refDoppler, _secDoppler, rngOffsetRaster, aziOffsetRaster, refDoppCentroids, secDoppCentroids); - maxKernelSize = _maximum_kernel_size(refDoppCentroids, + maxKernelSize = _computeMaxAzimuthFilterKernelSize(refDoppCentroids, secDoppCentroids, _azimuthBandwidth, _prf, _windowParameter, azimuthFilter); - debug << "max azimuth window kernel size: " << _maxFilterKernelSize << pyre::journal::endl; + debug << "max azimuth window kernel size: " << maxKernelSize << pyre::journal::endl; // to ensure the overlap size is an integer multiple number of azimuth looks. maxKernelSize = (maxKernelSize + _azimuthLooks) / _azimuthLooks; diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 1fd666af5..7d077a476 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -222,14 +222,14 @@ class isce3::signal::Crossmul { size_t ncols); private: - void _compute_DoppCentroids(const isce3::core::LUT2d & refDoppler, + void _computeDoppCentroids(const isce3::core::LUT2d & refDoppler, const isce3::core::LUT2d & secDoppler, isce3::io::Raster* rngOffsetRaster, isce3::io::Raster* aziOffsetRaster, std::valarray &refDopplerCentroids, std::valarray &secDopplerCentroids); - int _maximum_kernel_size(std::valarray &refDopplerCentroids, + int _computeMaxAzimuthFilterKernelSize(std::valarray &refDopplerCentroids, std::valarray &secDopplerCentroids, const double bandwidth, const double prf, diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 1420f1779..074540a64 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -187,8 +187,8 @@ isce3::signal::Filter::constructRangeCommonBandFilter(const double rangeSampl // construct a block of the filter, and normalize the transform to recovery the // input signal + #pragma omp parallel for for (size_t line = 0; line < nrows; line++ ){ - #pragma omp parallel for for (size_t col = 0; col < fft_size; col++ ){ _filter[line*fft_size+col] = _filter1D[col] / static_cast(fft_size); } @@ -451,8 +451,13 @@ constructAzimuthCommonBandFilter(const std::valarray & refDoppler, prf, windowParameter, ncols, nrows); } else{ - std::cout << filterType << " filter has not been implemented" << std::endl; - return bandwidth; + std::string err_str = filterType + " filter has not been implemented"; + pyre::journal::error_t err( + "isce.signal.Filter.constructAzimuthCommonBandFilter"); + err << err_str << pyre::journal::endl; + throw isce3::except::InvalidArgument(ISCE_SRCINFO(), + err_str); + return bandwidth; } } From b64ca8953413075cafd0fc505de97e430758bcec Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 13 Dec 2023 04:36:03 +0000 Subject: [PATCH 078/106] minors --- cxx/isce3/signal/Crossmul.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index f66143182..e8404b3cd 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -319,10 +319,10 @@ isce3::signal::Crossmul::_computeDoppCentroids(const isce3::core::LUT2d // process block by block #pragma omp parallel for for (size_t col = 0; col < ncols; col++) { - if (validNumbers[col] > 0) { - refDopplerCentroids[col] /= validNumbers[col]; - secDopplerCentroids[col] /= validNumbers[col]; - } + if (validNumbers[col] > 0) { + refDopplerCentroids[col] /= validNumbers[col]; + secDopplerCentroids[col] /= validNumbers[col]; + } } } From 2b8bf41d137756cc2d62b43d54d2902db1418595 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 13 Dec 2023 04:47:44 +0000 Subject: [PATCH 079/106] fix some readability --- cxx/isce3/signal/Crossmul.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index e8404b3cd..3c857db4b 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -391,7 +391,7 @@ crossmul(isce3::io::Raster& refSlcRaster, // Declare valarray for range and azimuth doppler centroids used by filter std::valarray refDoppCentroids; std::valarray secDoppCentroids; - int maxKernelSize = 0; + int maxAzimuthFilterKernelSize = 0; int overlapSize = 0; int halfOverlapSize = 0; @@ -408,22 +408,25 @@ crossmul(isce3::io::Raster& refSlcRaster, refDoppCentroids, secDoppCentroids); - maxKernelSize = _computeMaxAzimuthFilterKernelSize(refDoppCentroids, + maxAzimuthFilterKernelSize = _computeMaxAzimuthFilterKernelSize(refDoppCentroids, secDoppCentroids, _azimuthBandwidth, _prf, _windowParameter, azimuthFilter); - debug << "max azimuth window kernel size: " << maxKernelSize << pyre::journal::endl; + debug << "max azimuth window kernel size: " << maxAzimuthFilterKernelSize + << pyre::journal::endl; // to ensure the overlap size is an integer multiple number of azimuth looks. - maxKernelSize = (maxKernelSize + _azimuthLooks) / _azimuthLooks; + maxAzimuthFilterKernelSize = (maxAzimuthFilterKernelSize + _azimuthLooks) / _azimuthLooks; // Force the kernel size to be even - maxKernelSize = (maxKernelSize%2 == 0) ? maxKernelSize : maxKernelSize + 1; + maxAzimuthFilterKernelSize = + (maxAzimuthFilterKernelSize%2 == 0) ? + maxAzimuthFilterKernelSize : maxAzimuthFilterKernelSize + 1; // The overlap size will be even - overlapSize = maxKernelSize * _azimuthLooks; + overlapSize = maxAzimuthFilterKernelSize * _azimuthLooks; halfOverlapSize = overlapSize / 2; // Compute the lines per block to account for the overlaps between two blocks From 13e78684d8b15bd5f38024cc3f26d72a1acc05c3 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 13 Dec 2023 04:51:28 +0000 Subject: [PATCH 080/106] minors --- cxx/isce3/signal/Crossmul.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 3c857db4b..9de9f99ac 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -170,6 +170,7 @@ rangeCommonBandFilter(std::valarray> &refSlc, * @param[in] azimuthFilter a filter object * @param[in] blockLength number of rows * @param[in] ncols number of columns +* @return the processed azimuth bandwidth */ double isce3::signal::Crossmul:: azimuthCommonBandFilter(std::valarray> &refSlc, @@ -209,7 +210,7 @@ azimuthCommonBandFilter(std::valarray> &refSlc, * @param[in] prf pule repeat frequency * @param[in] beta kaiser window parameter * @param[in] aziFilter azimuth filter - +* @return the maximum azimuth filter kernel size */ int isce3::signal::Crossmul::_computeMaxAzimuthFilterKernelSize(std::valarray &refDopplerCentroids, From 7c1dcfc1700a6b5f91909cab9818cd1c2c0dfaf1 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 14 Dec 2023 00:35:20 +0000 Subject: [PATCH 081/106] change minors --- cxx/isce3/signal/Crossmul.cpp | 52 ++++++++++++++++++++++------------- cxx/isce3/signal/Crossmul.h | 20 ++++++-------- cxx/isce3/signal/Filter.cpp | 20 +++++++++++--- 3 files changed, 57 insertions(+), 35 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 9de9f99ac..133c3130e 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -77,6 +77,8 @@ size_t omp_thread_count() { * @param[in] rngFilter a filter object * @param[in] blockLength number of rows * @param[in] ncols number of columns +* @param[in] maxRangeFilterKernelSize maximum range filter kernel size +* @returns the common bandwidth */ double isce3::signal::Crossmul:: rangeCommonBandFilter(std::valarray> &refSlc, @@ -88,7 +90,8 @@ rangeCommonBandFilter(std::valarray> &refSlc, std::valarray &rangeFrequencies, isce3::signal::Filter &rngFilter, size_t blockLength, - size_t ncols) + size_t ncols, + const size_t maxRangeFilterKernelSize) { pyre::journal::debug_t debug("isce.signal.Crossmul.rangeCommonBandFilter"); @@ -121,8 +124,9 @@ rangeCommonBandFilter(std::valarray> &refSlc, const double filterBandwidth = _rangeBandwidth - fabs(frequencyShift); if (_windowType == "kaiser") { - auto [n, _] = rngFilter._kaiserord(40, 0.15 * filterBandwidth/_rangeSamplingFrequency); - if (n > _maxFilterKernelSize) { + auto [n, _] = rngFilter._kaiserord(_ripple, + _transitionWidth * filterBandwidth/_rangeSamplingFrequency); + if (n > maxRangeFilterKernelSize) { pyre::journal::error_t err( "isce.signal.Crossmul.rangeCommonBandFilter"); err << "Max filter length exceeded due to insufficient " @@ -142,7 +146,7 @@ rangeCommonBandFilter(std::valarray> &refSlc, blockLength, _windowType, _windowParameter, - _maxFilterKernelSize); + maxRangeFilterKernelSize); // low pass filter the ref slc rngFilter.initiateRangeFilter(refSlc,refSpectrum, ncols, blockLength); @@ -170,7 +174,7 @@ rangeCommonBandFilter(std::valarray> &refSlc, * @param[in] azimuthFilter a filter object * @param[in] blockLength number of rows * @param[in] ncols number of columns -* @return the processed azimuth bandwidth +* @returns the common azimuth bandwidth */ double isce3::signal::Crossmul:: azimuthCommonBandFilter(std::valarray> &refSlc, @@ -183,14 +187,12 @@ azimuthCommonBandFilter(std::valarray> &refSlc, size_t blockRows, size_t ncols) { - std::string filterType = _windowType; - // Construct azimuth common bandpass filter for both reference and secondary double processedAzimuthBandwidth = azimuthFilter.constructAzimuthCommonBandFilter( refDoppCentroids, secDoppCentroids, _azimuthBandwidth, _prf, _windowParameter, ncols, - blockRows, filterType); + blockRows, _windowType); // Filter a block of data of the reference azimuthFilter.initiateAzimuthFilter(refSlc, refAzimuthSpectrum, ncols, blockRows); @@ -218,9 +220,7 @@ isce3::signal::Crossmul::_computeMaxAzimuthFilterKernelSize(std::valarray &aziFilter, - const double stopatt, - const double transition_width) + isce3::signal::Filter &aziFilter) { int max_kernel_size = 0; @@ -232,12 +232,22 @@ isce3::signal::Crossmul::_computeMaxAzimuthFilterKernelSize(std::valarray 1.0) { pyre::journal::error_t err( "isce.signal.Crossmul._maximum_kernel_size"); @@ -247,7 +257,7 @@ isce3::signal::Crossmul::_computeMaxAzimuthFilterKernelSize(std::valarray max_kernel_size) max_kernel_size = n; } } @@ -366,20 +376,23 @@ crossmul(isce3::io::Raster& refSlcRaster, throw isce3::except::LengthError(ISCE_SRCINFO(), "interferogram and coherence rasters width do not match"); + // maximum range filter kernel size + size_t maxRangeFilterKernelSize = 256; + // Compute the range sampling frequency in Hz using the range pixel spacing _rangeSamplingFrequency = 1.0 / (_rangePixelSpacing*2.0/isce3::core::speed_of_light); if (_doCommonRangeBandFilter) { // Determine the max range filter kernel size // 40 is the ripple, 0.15 is the default transition width - auto [n, _] = rangeFilter._kaiserord(40.0, + auto [n, _] = rangeFilter._kaiserord(_ripple, _minRangeSpectrumOverlapFraction * - rangeBandwidth()/_rangeSamplingFrequency * 0.15); - _maxFilterKernelSize = n; - debug << "max range filter kernel size: " << _maxFilterKernelSize << pyre::journal::endl; + rangeBandwidth()/_rangeSamplingFrequency * _transitionWidth); + maxRangeFilterKernelSize = n; + debug << "max range filter kernel size: " << maxRangeFilterKernelSize << pyre::journal::endl; } // Compute FFT size (power of 2) and set up the maximum range window size - size_t fft_size = isce3::fft::nextFastPower(ncols + _maxFilterKernelSize); + size_t fft_size = isce3::fft::nextFastPower(ncols + maxRangeFilterKernelSize); if (fft_size > INT_MAX) throw isce3::except::LengthError(ISCE_SRCINFO(), "fft_size > INT_MAX"); @@ -751,7 +764,8 @@ crossmul(isce3::io::Raster& refSlcRaster, // and the resultant refSlc and secSlc have no topo phase removal _processedRangeBandwidth += rangeCommonBandFilter(refSlc, secSlc, geometryIfgram, geometryIfgramConj, refSpectrum, secSpectrum, - rangeFrequencies, rangeFilter, linesPerBlock, fft_size); + rangeFrequencies, rangeFilter, linesPerBlock, fft_size, + maxRangeFilterKernelSize); } // Apply the azimuth common band-pass filter to the reference and secondary SLCs diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 7d077a476..3f107c226 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -204,7 +204,8 @@ class isce3::signal::Crossmul { std::valarray &rangeFrequencies, isce3::signal::Filter &rngFilter, size_t blockRows, - size_t ncols); + size_t ncols, + const size_t maxRangeFilterKernelSize = 256); /** Azimuth common band filtering block by block @insar2007product //TODO: since there is no windowing is applied in azimuth, no need to revert @@ -234,9 +235,7 @@ class isce3::signal::Crossmul { const double bandwidth, const double prf, const double beta, - isce3::signal::Filter &aziFilter, - const double stopatt = 40.0, - const double transition_width = 0.15); + isce3::signal::Filter &aziFilter); //Doppler LUT for the refernce SLC isce3::core::LUT2d _refDoppler; @@ -315,14 +314,11 @@ class isce3::signal::Crossmul { // minimum range spectrum overlap fraction between reference and secondary RSLC double _minRangeSpectrumOverlapFraction = 0.2; - // maximum filter kernel size over the range - // which corresponding to about 20% range spectrum overlap - // Using the function kaiserord(40,1/1.5*0.15*0.2) - // where 1/1.5 is the bandwidth/fs, 0.15 is the default transition width - // 0.2 is the minimum overlapped spetrum fraction - // between reference and secodnay RSLC, then _maxFilterKernelSize is about 225 - // NOTE: this paramer is only used when the range common band filter is enabled. - int _maxFilterKernelSize = 0; + // ripple for the range FIR filter + double _ripple = 40.0; + + // transition width + double _transitionWidth = 0.15; }; // Get inline implementations for Crossmul diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 074540a64..adc9b92d1 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -415,7 +415,7 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, /** * @param[in] refDoppler Doppler Centroids, in Hz, of the reference SLC w.r.t slant range axis * @param[in] secDoppler Doppler Centroids, in Hz, of the secondary SLC w.r.t slant range axis -* @param[in] bandwidth common bandwidth in azimuth, in Hz +* @param[in] bandwidth input bandwidth in azimuth, in Hz * @param[in] prf pulse repetition frequency, in Hz * @param[in] windowParameter window parameter of the filter * @param[in] signal a block of data to filter @@ -464,7 +464,7 @@ constructAzimuthCommonBandFilter(const std::valarray & refDoppler, /** * @param[in] refDoppler Doppler Centroids, in Hz, of the reference SLC w.r.t slant range axis * @param[in] secDoppler Doppler Centroids, in Hz, of the secondary SLC w.r.t slant range axis -* @param[in] bandwidth common bandwidth in azimuth, in Hz +* @param[in] bandwidth input bandwidth in azimuth, in Hz * @param[in] prf pulse repetition frequency, in Hz * @param[in] beta parameter for raised cosine filter * @param[in] signal a block of data to filter @@ -519,7 +519,10 @@ constructAzimuthCommonBandCosineFilter(const std::valarray & refDoppler, for (size_t i = 0; i < frequency.size(); ++i) { // Get the absolute value of shifted frequency - const double freq = std::abs(frequency[i] - fmid); + double freq = std::abs(frequency[i] - fmid); + + // Wrap the frequency within the RPF + freq = freq - int(freq/prf) * prf; // Passband if (freq <= (0.5 * bandwidth - df)) { @@ -557,7 +560,7 @@ constructAzimuthCommonBandCosineFilter(const std::valarray & refDoppler, /** * @param[in] refDoppler Doppler Centroids, in Hz, of the reference SLC w.r.t slant range axis * @param[in] secDoppler Doppler Centroids, in Hz, of the secondary SLC w.r.t slant range axis -* @param[in] bandwidth common bandwidth in azimuth, in Hz +* @param[in] bandwidth input bandwidth in azimuth, in Hz * @param[in] prf pulse repetition frequency, in Hz * @param[in] beta parameter for kaiser filter * @param[in] signal a block of data to filter @@ -598,6 +601,15 @@ constructAzimuthCommonBandKaiserFilter(const std::valarray & refDoppler, double fmid = 0.5 * (refFreq + secFreq); double fshift = std::abs(refFreq - secFreq); + if (bandwidth < fshift) { + pyre::journal::error_t err( + "isce.signal.Filter.constructAzimuthCommonBandKaiserFilter"); + err << "Bandwith is less than frequency shift" + << pyre::journal::endl; + throw isce3::except::InvalidArgument(ISCE_SRCINFO(), + "Bandwith is less than frequency shift"); + } + std::valarray> kaiser; _design_shaped_lowpass_filter(bandwidth - fshift, prf, beta, kaiser); From c93885adc559202baaac7fe7399c8e6ac5aba5fb Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 14 Dec 2023 00:51:09 +0000 Subject: [PATCH 082/106] change the sensor type --- cxx/isce3/signal/Crossmul.h | 2 +- python/packages/nisar/workflows/crossmul.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 3f107c226..7f05c049b 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -282,7 +282,7 @@ class isce3::signal::Crossmul { double _processedAzimuthBandwidth = 0.0; // Sensor type - std::string _sensorType = "NISAR"; + std::string _sensorType = ""; // Window type std::string _windowType = "kaiser"; diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index ecf4892d5..2e89888f0 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -81,7 +81,8 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', # do the flatten crossmul.do_flatten = flatten # sensor type - crossmul.sensor_type = 'RS2' + crossmul.sensor_type = \ + ref_slc.identification.missionId crossmul.range_looks = rg_looks crossmul.az_looks = az_looks From 57b4de80b67378768d3a83a0fe6c7e0c5088b572 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 14 Dec 2023 01:08:04 +0000 Subject: [PATCH 083/106] change formats --- cxx/isce3/signal/Crossmul.cpp | 10 +++++----- cxx/isce3/signal/Crossmul.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 133c3130e..f60e50403 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -208,11 +208,11 @@ azimuthCommonBandFilter(std::valarray> &refSlc, /** * @param[in] refDopplerCentroids doppler centroid frequency for reference * @param[in] secDopplerCentroids doppler centroid frequency for secondary -* @param[in] bandwidth bandwidth -* @param[in] prf pule repeat frequency +* @param[in] bandwidth intput SLCs bandwidth +* @param[in] prf pulse repeat frequency * @param[in] beta kaiser window parameter * @param[in] aziFilter azimuth filter -* @return the maximum azimuth filter kernel size +* @returns the maximum azimuth filter kernel size */ int isce3::signal::Crossmul::_computeMaxAzimuthFilterKernelSize(std::valarray &refDopplerCentroids, @@ -269,8 +269,8 @@ isce3::signal::Crossmul::_computeMaxAzimuthFilterKernelSize(std::valarray & refDoppler, diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 7f05c049b..2056b8842 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -314,7 +314,7 @@ class isce3::signal::Crossmul { // minimum range spectrum overlap fraction between reference and secondary RSLC double _minRangeSpectrumOverlapFraction = 0.2; - // ripple for the range FIR filter + // ripple for the FIR filter double _ripple = 40.0; // transition width From b45d7f13b60a1cb6d8c36aac82c13f450d0badfd Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 14 Dec 2023 01:32:25 +0000 Subject: [PATCH 084/106] some readability changes --- cxx/isce3/signal/Crossmul.h | 2 +- cxx/isce3/signal/Filter.cpp | 25 +++++++++++++++++++------ cxx/isce3/signal/Filter.h | 2 +- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 2056b8842..e94a283c4 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -302,7 +302,7 @@ class isce3::signal::Crossmul { // range signal bandwidth in Hz double _rangeBandwidth = 0.0; - // Processed range bandwidth after the common band filtering in Hz + // Processed range bandwidth after the common band filtering, in Hz double _processedRangeBandwidth = 0.0; // number of lines per block diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index adc9b92d1..3a953c751 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -127,7 +127,12 @@ constructRangeBandpassFilter(double rangeSamplingFrequency, beta, _filter1D); } else { - std::cout << filterType << " filter has not been implemented" << std::endl; + std::string err_str = filterType + " filter has not been implemented"; + pyre::journal::error_t err( + "isce.signal.Filter.constructRangeBandpassFilter"); + err << err_str << pyre::journal::endl; + throw isce3::except::InvalidArgument(ISCE_SRCINFO(), + err_str); } //construct a block of the filter with normalization @@ -457,7 +462,6 @@ constructAzimuthCommonBandFilter(const std::valarray & refDoppler, err << err_str << pyre::journal::endl; throw isce3::except::InvalidArgument(ISCE_SRCINFO(), err_str); - return bandwidth; } } @@ -499,20 +503,28 @@ constructAzimuthCommonBandCosineFilter(const std::valarray & refDoppler, std::valarray frequency(fft_size); fftfreq(1.0/prf, frequency); + // mean doppler center frequency and + // dopper frequency shift between Reference and Secondary double meanDopCenterFreq = 0.0; double meanDopCenterFreqShift = 0.0; + // Loop over range bins for (int j = 0; j < ncols; ++j) { - // Compute center frequency of common band - // I think we need the range offsets here to restore the fDC - // for the secondary doppler since it is the resampled RSLC - // middle frequency for the reference SLC double refFreq = refDoppler[j]; double secFreq = secDoppler[j]; double fmid = 0.5 * (refFreq + secFreq); double fshift = std::abs(refFreq - secFreq); + if (fshift > bandwidth) { + pyre::journal::error_t err( + "isce.signal.Filter.constructAzimuthCommonBandCosineFilter"); + err << "Bandwith is less than frequency shift" + << pyre::journal::endl; + throw isce3::except::InvalidArgument(ISCE_SRCINFO(), + "Bandwith is less than frequency shift"); + } + meanDopCenterFreqShift += fshift; meanDopCenterFreq += fmid; // Compute filter @@ -567,6 +579,7 @@ constructAzimuthCommonBandCosineFilter(const std::valarray & refDoppler, * @param[in] spectrum of the block of data * @param[in] ncols number of columns of the block of data * @param[in] nrows number of rows of the block of data +* @returns common azimuth bandwidth */ template double diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index ab3fb5fc7..f3bb10a1f 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -162,7 +162,7 @@ class isce3::signal::Filter { /** Determine the filter window parameters for the Kaiser window method * @param[in] ripple Upper bound for the deviation (in dB) of the magnitude of the filter's frequency response from that of the desired filter (not including frequencies in any transition intervals). * @param[in] transition_width Width of transition region, normalized so that 1 corresponds to pi radians / sample. - * @return the length and the beta of the Kaiser window. + * @returns the length and the beta of the Kaiser window. */ std::tuple _kaiserord(const double ripple, const double transition_width); From 123ec1ca80ccc43b5d4f1a2dd8226b1d81f06f11 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 14 Dec 2023 01:34:40 +0000 Subject: [PATCH 085/106] docstrings --- cxx/isce3/signal/Filter.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 3a953c751..2db93cb7c 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -427,6 +427,7 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, * @param[in] spectrum of the block of data * @param[in] ncols number of columns of the block of data * @param[in] nrows number of rows of the block of data +* @return new bandwidth */ template double @@ -441,6 +442,7 @@ constructAzimuthCommonBandFilter(const std::valarray & refDoppler, std::string& filterType) { if (filterType=="cosine"){ + // Cosine filter is constructed in the frequency domain return constructAzimuthCommonBandCosineFilter( refDoppler, secDoppler, @@ -449,6 +451,7 @@ constructAzimuthCommonBandFilter(const std::valarray & refDoppler, ncols, nrows); } else if (filterType=="kaiser"){ + // Kaiser filter is constructed in the time domain return constructAzimuthCommonBandKaiserFilter( refDoppler, secDoppler, From 8944067ae2799e6391ad1a7e23a13b692815cc2a Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 14 Dec 2023 04:14:15 +0000 Subject: [PATCH 086/106] fix the invalid dopp centroids computation --- .vscode/settings.json | 68 +++++++++++++++++++++++++++++++++++ cxx/isce3/signal/Crossmul.cpp | 32 +++++++++++------ cxx/isce3/signal/Crossmul.h | 4 ++- 3 files changed, 92 insertions(+), 12 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..a8ddd9f34 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,68 @@ +{ + "files.associations": { + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "set": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "valarray": "cpp", + "variant": "cpp" + } +} \ No newline at end of file diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index f60e50403..60c626f7a 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -208,6 +208,7 @@ azimuthCommonBandFilter(std::valarray> &refSlc, /** * @param[in] refDopplerCentroids doppler centroid frequency for reference * @param[in] secDopplerCentroids doppler centroid frequency for secondary +* @param[in] numOfDopplerCentroids number of valid doppler centroids * @param[in] bandwidth intput SLCs bandwidth * @param[in] prf pulse repeat frequency * @param[in] beta kaiser window parameter @@ -217,6 +218,7 @@ azimuthCommonBandFilter(std::valarray> &refSlc, int isce3::signal::Crossmul::_computeMaxAzimuthFilterKernelSize(std::valarray &refDopplerCentroids, std::valarray &secDopplerCentroids, + std::valarray &numOfValidDopplerCentroids, const double bandwidth, const double prf, const double beta, @@ -227,7 +229,7 @@ isce3::signal::Crossmul::_computeMaxAzimuthFilterKernelSize(std::valarray 0 && std::abs(secDopplerCentroids[j]) > 0) { + if (numOfValidDopplerCentroids[j] > 0) { double refFreq = refDopplerCentroids[j]; double secFreq = secDopplerCentroids[j]; double fshift = std::abs(refFreq - secFreq); @@ -251,7 +253,7 @@ isce3::signal::Crossmul::_computeMaxAzimuthFilterKernelSize(std::valarray 1.0) { pyre::journal::error_t err( "isce.signal.Crossmul._maximum_kernel_size"); - err << "Passband + transition cannot exceed Nyquis " + err << "Passband + transition cannot exceed Nyquist" << pyre::journal::endl; throw isce3::except::InvalidArgument(ISCE_SRCINFO(), "Passband + transition cannot exceed Nyquist"); @@ -271,6 +273,8 @@ isce3::signal::Crossmul::_computeMaxAzimuthFilterKernelSize(std::valarray & refDoppler, @@ -278,7 +282,8 @@ isce3::signal::Crossmul::_computeDoppCentroids(const isce3::core::LUT2d isce3::io::Raster* rngOffsetRaster, isce3::io::Raster* aziOffsetRaster, std::valarray &refDopplerCentroids, - std::valarray &secDopplerCentroids) + std::valarray &secDopplerCentroids, + std::valarray &numOfValidDopplerCentroids) { const size_t ncols = rngOffsetRaster->width(); const size_t nrows = rngOffsetRaster->length(); @@ -291,9 +296,10 @@ isce3::signal::Crossmul::_computeDoppCentroids(const isce3::core::LUT2d secDopplerCentroids.resize(ncols); secDopplerCentroids = 0.0; } - - std::valarray validNumbers(ncols); - validNumbers = 0; + if (numOfValidDopplerCentroids.size() <= 0) { + numOfValidDopplerCentroids.resize(ncols); + numOfValidDopplerCentroids = 0; + } // Compute the doppler centroids for the reference and secondary images #pragma omp parallel for @@ -321,7 +327,7 @@ isce3::signal::Crossmul::_computeDoppCentroids(const isce3::core::LUT2d if (refDoppler.contains(refY, refX) && secDoppler.contains(secY, secX)) { refDopplerCentroids[col] += refDoppler.eval(refY, refX); secDopplerCentroids[col] += secDoppler.eval(secY, secX); - validNumbers[col]++; + numOfValidDopplerCentroids[col]++; } } } @@ -330,9 +336,9 @@ isce3::signal::Crossmul::_computeDoppCentroids(const isce3::core::LUT2d // process block by block #pragma omp parallel for for (size_t col = 0; col < ncols; col++) { - if (validNumbers[col] > 0) { - refDopplerCentroids[col] /= validNumbers[col]; - secDopplerCentroids[col] /= validNumbers[col]; + if (numOfValidDopplerCentroids[col] > 0) { + refDopplerCentroids[col] /= numOfValidDopplerCentroids[col]; + secDopplerCentroids[col] /= numOfValidDopplerCentroids[col]; } } } @@ -405,6 +411,7 @@ crossmul(isce3::io::Raster& refSlcRaster, // Declare valarray for range and azimuth doppler centroids used by filter std::valarray refDoppCentroids; std::valarray secDoppCentroids; + std::valarray numOfValidDoppCentroids; int maxAzimuthFilterKernelSize = 0; int overlapSize = 0; int halfOverlapSize = 0; @@ -414,16 +421,19 @@ crossmul(isce3::io::Raster& refSlcRaster, // the reference and secondary images for each slant range refDoppCentroids.resize(fft_size); refDoppCentroids = 0.0; secDoppCentroids.resize(fft_size); secDoppCentroids = 0.0; + numOfValidDoppCentroids.resize(fft_size); numOfValidDoppCentroids = 0; info << "determine the max azimuth kernel size" << pyre::journal::newline; _computeDoppCentroids(_refDoppler, _secDoppler, rngOffsetRaster, aziOffsetRaster, refDoppCentroids, - secDoppCentroids); + secDoppCentroids, + numOfValidDoppCentroids); maxAzimuthFilterKernelSize = _computeMaxAzimuthFilterKernelSize(refDoppCentroids, secDoppCentroids, + numOfValidDoppCentroids, _azimuthBandwidth, _prf, _windowParameter, diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index e94a283c4..ad708a02c 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -228,10 +228,12 @@ class isce3::signal::Crossmul { isce3::io::Raster* rngOffsetRaster, isce3::io::Raster* aziOffsetRaster, std::valarray &refDopplerCentroids, - std::valarray &secDopplerCentroids); + std::valarray &secDopplerCentroids, + std::valarray &numOfValidDopplerCentroids); int _computeMaxAzimuthFilterKernelSize(std::valarray &refDopplerCentroids, std::valarray &secDopplerCentroids, + std::valarray &numOfValidDopplerCentroids, const double bandwidth, const double prf, const double beta, From 797de551b527299357076359024571d7e71f7b47 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 14 Dec 2023 04:14:43 +0000 Subject: [PATCH 087/106] remove .vscode --- .vscode/settings.json | 68 ------------------------------------------- 1 file changed, 68 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index a8ddd9f34..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "files.associations": { - "any": "cpp", - "array": "cpp", - "atomic": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "chrono": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "complex": "cpp", - "condition_variable": "cpp", - "csignal": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "list": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "map": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "regex": "cpp", - "set": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "new": "cpp", - "ostream": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "cinttypes": "cpp", - "typeindex": "cpp", - "typeinfo": "cpp", - "valarray": "cpp", - "variant": "cpp" - } -} \ No newline at end of file From e41f074a0d04bcc0f09221f5e3a127a84b1d3e25 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 14 Dec 2023 04:53:15 +0000 Subject: [PATCH 088/106] remove redundant descriptions --- cxx/isce3/signal/Crossmul.cpp | 1 - tests/cxx/isce3/cuda/signal/gpuCrossMul.cpp | 6 +++--- tests/cxx/isce3/signal/crossmul.cpp | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 60c626f7a..aef298de9 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -389,7 +389,6 @@ crossmul(isce3::io::Raster& refSlcRaster, _rangeSamplingFrequency = 1.0 / (_rangePixelSpacing*2.0/isce3::core::speed_of_light); if (_doCommonRangeBandFilter) { // Determine the max range filter kernel size - // 40 is the ripple, 0.15 is the default transition width auto [n, _] = rangeFilter._kaiserord(_ripple, _minRangeSpectrumOverlapFraction * rangeBandwidth()/_rangeSamplingFrequency * _transitionWidth); diff --git a/tests/cxx/isce3/cuda/signal/gpuCrossMul.cpp b/tests/cxx/isce3/cuda/signal/gpuCrossMul.cpp index ae596ad36..51b89061b 100644 --- a/tests/cxx/isce3/cuda/signal/gpuCrossMul.cpp +++ b/tests/cxx/isce3/cuda/signal/gpuCrossMul.cpp @@ -48,7 +48,7 @@ TEST(gpuCrossmul, Crossmul) // Create a product isce3::product::RadarGridProduct product(file); - // get the Doppler polynomial for refernce SLC + // get the Doppler for refernce SLC const isce3::core::LUT2d dop1 = product.metadata().procInfo().dopplerCentroid('A'); @@ -59,7 +59,7 @@ TEST(gpuCrossmul, Crossmul) //instantiate the Crossmul class isce3::cuda::signal::gpuCrossmul crsmul; - // set Doppler polynomials for refernce and secondary SLCs + // set Doppler for refernce and secondary SLCs crsmul.doppler(dop1, dop2); // set number of interferogram looks in range @@ -135,7 +135,7 @@ TEST(gpuCrossmul, MultilookCrossmul) //instantiate the Crossmul class isce3::cuda::signal::gpuCrossmul crsmul; - // set Doppler polynomials for refernce and secondary SLCs + // set Doppler for refernce and secondary SLCs crsmul.doppler(dop1, dop2); // set number of interferogram looks in range diff --git a/tests/cxx/isce3/signal/crossmul.cpp b/tests/cxx/isce3/signal/crossmul.cpp index 0bfbdcd84..7fc321a82 100644 --- a/tests/cxx/isce3/signal/crossmul.cpp +++ b/tests/cxx/isce3/signal/crossmul.cpp @@ -47,7 +47,7 @@ TEST(Crossmul, RunCrossmul) // Create a product isce3::product::RadarGridProduct product(file); - // get the Doppler polynomial for refernce SLC + // get the Doppler for refernce SLC isce3::core::LUT2d dop1 = product.metadata().procInfo().dopplerCentroid('A'); // Since this test careates an interferogram between the refernce SLC and itself, @@ -57,7 +57,7 @@ TEST(Crossmul, RunCrossmul) //instantiate the Crossmul class isce3::signal::Crossmul crsmul; - // set Doppler polynomials for refernce and secondary SLCs + // set Doppler for refernce and secondary SLCs crsmul.doppler(dop1, dop2); // set number of interferogram looks in range From 3df640b6d825a5c9c277bced6c3a172ffe4eb422 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 14 Dec 2023 05:20:39 +0000 Subject: [PATCH 089/106] fix minors --- cxx/isce3/signal/Filter.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 2db93cb7c..23b8f1620 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -605,7 +605,10 @@ constructAzimuthCommonBandKaiserFilter(const std::valarray & refDoppler, isce3::signal::Signal doppSignal; doppSignal.forwardRangeFFT(filter1D, filter1D, fft_size, 1); + // azimuth mean doppler centroid frequency, in Hz double meanDopCenterFreq = 0.0; + + // azimuth mean doppler center frequency shift, in Hz double meanDopCenterFreqShift = 0.0; // Loop over range bins @@ -637,10 +640,11 @@ constructAzimuthCommonBandKaiserFilter(const std::valarray & refDoppler, if (fft_size < sizeOfKaiser) { pyre::journal::error_t err( "isce.signal.Filter.constructAzimuthCommonBandKaiserFilter"); - err << "FFT size is less than the window size " + err << "FFT size " << fft_size <<" is less than the filter kernel size " + << sizeOfKaiser << pyre::journal::endl; throw isce3::except::LengthError(ISCE_SRCINFO(), - "FFT size is less than the window size"); + "FFT size is less than the filter kernel size"); } // Zero padding the filter in the middle @@ -659,7 +663,7 @@ constructAzimuthCommonBandKaiserFilter(const std::valarray & refDoppler, meanDopCenterFreq += fmid; // Copy the the filter centered at fmid to a block filter - // and Normalize the transform the recovery the input signal via + // and normalize the transform to recovery the input signal via // dividing by fft_size for (size_t i = 0; i < filter1D.size(); ++i) { _filter[i*ncols+j] = filter1D[i] / static_cast(fft_size); From b484d305dfa949d74d1632bf1800a2159b517aa0 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 14 Dec 2023 06:27:04 +0000 Subject: [PATCH 090/106] fix minors --- cxx/isce3/signal/Crossmul.cpp | 11 +++++++---- cxx/isce3/signal/Crossmul.h | 10 ++++++++-- cxx/isce3/signal/Filter.cpp | 6 +++--- python/extensions/pybind_isce3/signal/Crossmul.cpp | 4 ++++ 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index aef298de9..3cc64c62d 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -522,6 +522,8 @@ crossmul(isce3::io::Raster& refSlcRaster, } // set up the processed azimuth and range bandwidth + // if common band filters are enabled, they will be the mean bandwidth of all data block + // otherwise, they are the original SLC bandwidths _processedAzimuthBandwidth = _doCommonAzimuthBandFilter ? 0.0 : _azimuthBandwidth; _processedRangeBandwidth = _doCommonRangeBandFilter ? 0.0 : _rangeBandwidth; @@ -541,10 +543,11 @@ crossmul(isce3::io::Raster& refSlcRaster, std::valarray rngOffset(spectrumSize); // InSAR phase due to topography - // geometryIfgram = (4*PI/wavelength)*(rangePixelSpacing)*(rngOffset) std::valarray> geometryIfgram; // complex conjugate of geometryIfgram + // both the flattening and range common band filtering will use + // this variable, so creating a buffer here std::valarray> geometryIfgramConj(spectrumSize); // upsampled interferogram @@ -846,7 +849,7 @@ crossmul(isce3::io::Raster& refSlcRaster, nrowsMultiLooked /= _azimuthLooks; // The first block - std::slice dataSlice = std::slice(0,ncolsMultiLooked * nrowsMultiLooked, 1); + std::slice dataSlice = std::slice(0, ncolsMultiLooked * nrowsMultiLooked, 1); if (block > 0) { rowNewStart = (rowStart + halfOverlapSize)/_azimuthLooks; if (block != (nblocks - 1)) { @@ -899,10 +902,10 @@ crossmul(isce3::io::Raster& refSlcRaster, rowNewStart = rowStart + halfOverlapSize; if (block != (nblocks - 1)) { nrowsValid = blockRowsData - overlapSize; - dataSlice = std::slice(halfOverlapSize*ncols,nrowsValid, 1); + dataSlice = std::slice(halfOverlapSize * ncols, nrowsValid, 1); } else { // the last block nrowsValid = blockRowsData - halfOverlapSize; - dataSlice = std::slice(halfOverlapSize*ncols,nrowsValid, 1); + dataSlice = std::slice(halfOverlapSize * ncols,nrowsValid, 1); } } diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index ad708a02c..7dfd5eda3 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -111,7 +111,10 @@ class isce3::signal::Crossmul { inline double azimuthBandwidth() const { return _azimuthBandwidth; } - /** Get processed azimuth bandwidth, in Hz */ + /** Get processed azimuth bandwidth, in Hz. + * This is the average azimuth bandwidth after + * common-band filtering from among all blocks. + */ inline double processedAzimuthBandwidth() const { return _processedAzimuthBandwidth; } @@ -164,7 +167,10 @@ class isce3::signal::Crossmul { /** Get the range bandwidth, in Hz */ inline double rangeBandwidth() const {return _rangeBandwidth; } - /** Get processed range bandwidth after common band filter*/ + /** Get processed range bandwidth after common band filter + * This is the average range bandwidth after + * common-band filtering from among all blocks. + */ inline double processedRangeBandwidth() const { return _processedRangeBandwidth; } diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 23b8f1620..c96eddff0 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -420,7 +420,7 @@ constructRangeBandpassKaiser(std::valarray subBandCenterFrequencies, /** * @param[in] refDoppler Doppler Centroids, in Hz, of the reference SLC w.r.t slant range axis * @param[in] secDoppler Doppler Centroids, in Hz, of the secondary SLC w.r.t slant range axis -* @param[in] bandwidth input bandwidth in azimuth, in Hz +* @param[in] bandwidth input bandwidth in azimuth of the pair of SLCs, in Hz * @param[in] prf pulse repetition frequency, in Hz * @param[in] windowParameter window parameter of the filter * @param[in] signal a block of data to filter @@ -471,7 +471,7 @@ constructAzimuthCommonBandFilter(const std::valarray & refDoppler, /** * @param[in] refDoppler Doppler Centroids, in Hz, of the reference SLC w.r.t slant range axis * @param[in] secDoppler Doppler Centroids, in Hz, of the secondary SLC w.r.t slant range axis -* @param[in] bandwidth input bandwidth in azimuth, in Hz +* @param[in] bandwidth input bandwidth in azimuth of the pair of SLCs, in Hz * @param[in] prf pulse repetition frequency, in Hz * @param[in] beta parameter for raised cosine filter * @param[in] signal a block of data to filter @@ -575,7 +575,7 @@ constructAzimuthCommonBandCosineFilter(const std::valarray & refDoppler, /** * @param[in] refDoppler Doppler Centroids, in Hz, of the reference SLC w.r.t slant range axis * @param[in] secDoppler Doppler Centroids, in Hz, of the secondary SLC w.r.t slant range axis -* @param[in] bandwidth input bandwidth in azimuth, in Hz +* @param[in] bandwidth input bandwidth in azimuth of the pair of SLCs, in Hz * @param[in] prf pulse repetition frequency, in Hz * @param[in] beta parameter for kaiser filter * @param[in] signal a block of data to filter diff --git a/python/extensions/pybind_isce3/signal/Crossmul.cpp b/python/extensions/pybind_isce3/signal/Crossmul.cpp index 768b81fdc..035eb5737 100644 --- a/python/extensions/pybind_isce3/signal/Crossmul.cpp +++ b/python/extensions/pybind_isce3/signal/Crossmul.cpp @@ -47,6 +47,10 @@ void addbinding(py::class_ & pyCrossmul) interferogram: Raster Optional range offset raster usef for flattening and common band filter Optional range offset raster usef for azimuth common band filter + range_bandwidth: float + range bandwidth of the reference SLC + azimuth_bandwidth: float + azimuth bandwidth of the reference SLC )") .def("set_dopplers", &Crossmul::doppler, py::arg("ref_doppler"), From 6eebb9636e14823f42e18f0bf278a40704892d99 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 14 Dec 2023 06:42:26 +0000 Subject: [PATCH 091/106] minors --- cxx/isce3/signal/Crossmul.cpp | 19 +++++++++++++------ cxx/isce3/signal/Filter.cpp | 17 +++++++++-------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 3cc64c62d..809d0f648 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -103,8 +103,12 @@ rangeCommonBandFilter(std::valarray> &refSlc, // (slope-dependent) wavenumber. This shift in frequency domain is // achieved by removing/adding the geometrical phase (representing topography) // from/to reference and secondary SLCs in time domain. - refSlc *= geometryIfgramConj; - secSlc *= geometryIfgram; + #pragma omp parallel for + for (size_t i = 0; i < refSlc.size(); i++) { + refSlc[i] *= geometryIfgramConj[i]; + secSlc[i] *= geometryIfgram[i]; + } + // determine the frequency shift, in Hz based on the power spectral density of // the geometrical interferometric phase using an empirical approach @@ -158,8 +162,11 @@ rangeCommonBandFilter(std::valarray> &refSlc, // restore the original phase without the geometry phase // in case other steps will use the original phase - refSlc *= geometryIfgram; - secSlc *= geometryIfgramConj; + #pragma omp parallel for + for (size_t i = 0; i < refSlc.size(); i++) { + refSlc[i] *= geometryIfgram[i]; + secSlc[i] *= geometryIfgramConj[i]; + } return filterBandwidth; } @@ -854,11 +861,11 @@ crossmul(isce3::io::Raster& refSlcRaster, rowNewStart = (rowStart + halfOverlapSize)/_azimuthLooks; if (block != (nblocks - 1)) { nrowsMultiLooked = (blockRowsData - overlapSize) / _azimuthLooks; - dataSlice = std::slice(halfOverlapSize/_azimuthLooks*ncolsMultiLooked, + dataSlice = std::slice(halfOverlapSize/_azimuthLooks * ncolsMultiLooked, ncolsMultiLooked * nrowsMultiLooked, 1); } else { // The last block nrowsMultiLooked = (blockRowsData - halfOverlapSize) / _azimuthLooks; - dataSlice = std::slice(halfOverlapSize/_azimuthLooks*ncolsMultiLooked, + dataSlice = std::slice(halfOverlapSize/_azimuthLooks * ncolsMultiLooked, ncolsMultiLooked * nrowsMultiLooked, 1); } } diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index c96eddff0..ec869dbd6 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -450,7 +450,8 @@ constructAzimuthCommonBandFilter(const std::valarray & refDoppler, prf, windowParameter, ncols, nrows); - } else if (filterType=="kaiser"){ + } + if (filterType=="kaiser"){ // Kaiser filter is constructed in the time domain return constructAzimuthCommonBandKaiserFilter( refDoppler, @@ -458,14 +459,14 @@ constructAzimuthCommonBandFilter(const std::valarray & refDoppler, bandwidth, prf, windowParameter, ncols, nrows); - } else{ - std::string err_str = filterType + " filter has not been implemented"; - pyre::journal::error_t err( - "isce.signal.Filter.constructAzimuthCommonBandFilter"); - err << err_str << pyre::journal::endl; - throw isce3::except::InvalidArgument(ISCE_SRCINFO(), - err_str); } + + std::string err_str = filterType + " filter has not been implemented"; + pyre::journal::error_t err( + "isce.signal.Filter.constructAzimuthCommonBandFilter"); + err << err_str << pyre::journal::endl; + throw isce3::except::InvalidArgument(ISCE_SRCINFO(), + err_str); } /** From ad244869811a3458377b7cf237787547624808ff Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 14 Dec 2023 20:36:29 +0000 Subject: [PATCH 092/106] add the envisat.h5 offset product --- tests/data/envisat_offsets.tif | Bin 0 -> 19158 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/data/envisat_offsets.tif diff --git a/tests/data/envisat_offsets.tif b/tests/data/envisat_offsets.tif new file mode 100644 index 0000000000000000000000000000000000000000..bf86bbee70210295cad1fc95ae761eecd51db680 GIT binary patch literal 19158 zcmeI1J4{ny97n%W1Yd}#6dxd{^r9%@^YW+_MZ7%Xqfq!T#z$0o@r7*HiNwL&IA}tQ zX&lrz6yuZizA9z?K^G69SfM$r@v_;H))f8oYJJEP&4vUWTv?e*-?a z<@jJX;zLk@zX>0l&G_JL!3Vz*AHo=Z6+XCI@xgAxhhRJY4t#K`@xiOX2Y)9%gtho} z_~7os2fG^|f<5^4_~69x!E^AzZ@`CeFaAD!a2xT#?#GAV0DcobI0x~;YsLrv5I%&5 z@sHqxdlVn+F?YrH*lC_gPBLi*q+4BuA`Z5EvBhy!#U!L>RZMlW9mRA=>)3b}q6CH0;w+Gwfv1i@6 zfjfh98Ta+Y_k(wb+NbQt;ScuS(A-k+_4=nv_iZAc{XY8n@|c~^O#c|4x$f7bPduD^7Bs_SL#CuqM# z`%&7j)Bd6MSGE7F{dx5Q^#b(*^#b(*^#b(*^#b(*^#b(*^#b(*^#b(*^#b(*^#b(* z^#b(*^#b(*^#b(*^#b(*^#b(*^#b(*^#b(*^#b(*^#b(*^#b(*^#b(*^#b(*^#b*R If9nN*0se9WjQ{`u literal 0 HcmV?d00001 From 27a38a33234138cddf104b24c877e8441b84e95e Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 14 Dec 2023 21:59:57 +0000 Subject: [PATCH 093/106] add common band filtering to unit tests --- cxx/isce3/product/Swath.h | 2 +- cxx/isce3/signal/Crossmul.cpp | 3 ++ tests/cxx/isce3/signal/crossmul.cpp | 70 +++++++++++++++++++++++++++-- 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/cxx/isce3/product/Swath.h b/cxx/isce3/product/Swath.h index 180dc825b..58780e288 100644 --- a/cxx/isce3/product/Swath.h +++ b/cxx/isce3/product/Swath.h @@ -118,7 +118,7 @@ class isce3::product::Swath { inline isce3::product::SubSwaths& subSwaths() { return _subSwaths; } - + inline const isce3::product::SubSwaths& subSwaths() const { return _subSwaths; } diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 809d0f648..2fea120b8 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -651,6 +651,9 @@ crossmul(isce3::io::Raster& refSlcRaster, if (_doCommonRangeBandFilter) { geometryIfgram.resize(spectrumSize); + refSpectrum.resize(spectrumSize); + secSpectrum.resize(spectrumSize); + rangeFrequencies.resize(fft_size); // Compute the range frequency for each pixel diff --git a/tests/cxx/isce3/signal/crossmul.cpp b/tests/cxx/isce3/signal/crossmul.cpp index 7fc321a82..9974b6116 100644 --- a/tests/cxx/isce3/signal/crossmul.cpp +++ b/tests/cxx/isce3/signal/crossmul.cpp @@ -26,6 +26,10 @@ TEST(Crossmul, RunCrossmul) //a raster object for the reference SLC isce3::io::Raster referenceSlc(TESTDATA_DIR "warped_envisat.slc.vrt"); + //a raster object for the range and azimuth offsets + isce3::io::Raster aziOffsets(TESTDATA_DIR "envisat_offsets.tif"); + isce3::io::Raster rngOffsets(TESTDATA_DIR "envisat_offsets.tif"); + // get the length and width of the SLC int width = referenceSlc.width(); int length = referenceSlc.length(); @@ -48,7 +52,8 @@ TEST(Crossmul, RunCrossmul) isce3::product::RadarGridProduct product(file); // get the Doppler for refernce SLC - isce3::core::LUT2d dop1 = product.metadata().procInfo().dopplerCentroid('A'); + const char freq = 'A'; + isce3::core::LUT2d dop1 = product.metadata().procInfo().dopplerCentroid(freq); // Since this test careates an interferogram between the refernce SLC and itself, // the second Doppler is the same as the first @@ -66,8 +71,34 @@ TEST(Crossmul, RunCrossmul) // set number of interferogram looks in azimuth crsmul.azimuthLooks(1); + // set the product information for the common band filtering and flattenning + const double wavelength = product.swath(freq).processedWavelength(); + const double azimuthBandwidth = product.swath(freq).processedAzimuthBandwidth(); + const double rangeBandwidth = product.swath(freq).processedRangeBandwidth(); + const double prf = product.swath(freq).nominalAcquisitionPRF(); + const double rngPixelSampling = product.swath(freq).rangePixelSpacing(); + const double startAzimuthTime = product.swath(freq).zeroDopplerTime()[0]; + const double startSlantRange = product.swath(freq).slantRange()[0]; + + crsmul.wavelength(wavelength); + crsmul.prf(prf); + crsmul.rangePixelSpacing(rngPixelSampling); + crsmul.azimuthBandwidth(azimuthBandwidth); + crsmul.rangeBandwidth(rangeBandwidth); + crsmul.refStartRange(startSlantRange); + crsmul.secStartRange(startSlantRange); + crsmul.refStartAzimuthTime(startAzimuthTime); + crsmul.secStartAzimuthTime(startAzimuthTime); + + // Enable the flattening and common band filtering + crsmul.doFlatten(true); + crsmul.doCommonRangeBandFilter(true); + crsmul.doCommonAzimuthBandFilter(true); + // running crossmul - crsmul.crossmul(referenceSlc, referenceSlc, interferogram, coherence); + crsmul.crossmul(referenceSlc, referenceSlc, + interferogram, coherence, + &rngOffsets, &aziOffsets); // an array for the computed interferogram std::valarray> data(width*length); @@ -96,6 +127,10 @@ TEST(Crossmul, RunCrossmulMLook) //a raster object for the reference SLC isce3::io::Raster referenceSlc(TESTDATA_DIR "warped_envisat.slc.vrt"); + //a raster object for the range and azimuth offsets + isce3::io::Raster aziOffsets(TESTDATA_DIR "envisat_offsets.tif"); + isce3::io::Raster rngOffsets(TESTDATA_DIR "envisat_offsets.tif"); + // define looks const int rngLooks = 3; const int azLooks = 13; @@ -122,7 +157,8 @@ TEST(Crossmul, RunCrossmulMLook) isce3::product::RadarGridProduct product(file); // get the Doppler polynomial for refernce SLC - isce3::core::LUT2d dop1 = product.metadata().procInfo().dopplerCentroid('A'); + const char freq = 'A'; + isce3::core::LUT2d dop1 = product.metadata().procInfo().dopplerCentroid(freq); // Since this test careates an interferogram between the refernce SLC and itself, // the second Doppler is the same as the first @@ -140,8 +176,34 @@ TEST(Crossmul, RunCrossmulMLook) // set number of interferogram looks in azimuth crsmul.azimuthLooks(azLooks); + // set the product information for the common band filtering and flattenning + const double wavelength = product.swath(freq).processedWavelength(); + const double azimuthBandwidth = product.swath(freq).processedAzimuthBandwidth(); + const double rangeBandwidth = product.swath(freq).processedRangeBandwidth(); + const double prf = product.swath(freq).nominalAcquisitionPRF(); + const double rngPixelSampling = product.swath(freq).rangePixelSpacing(); + const double startAzimuthTime = product.swath(freq).zeroDopplerTime()[0]; + const double startSlantRange = product.swath(freq).slantRange()[0]; + + crsmul.wavelength(wavelength); + crsmul.prf(prf); + crsmul.rangePixelSpacing(rngPixelSampling); + crsmul.azimuthBandwidth(azimuthBandwidth); + crsmul.rangeBandwidth(rangeBandwidth); + crsmul.refStartRange(startSlantRange); + crsmul.secStartRange(startSlantRange); + crsmul.refStartAzimuthTime(startAzimuthTime); + crsmul.secStartAzimuthTime(startAzimuthTime); + + // Enable the flattening and common band filtering + crsmul.doFlatten(true); + crsmul.doCommonRangeBandFilter(true); + crsmul.doCommonAzimuthBandFilter(true); + // running crossmul - crsmul.crossmul(referenceSlc, referenceSlc, interferogram, coherence); + crsmul.crossmul(referenceSlc, referenceSlc, + interferogram, coherence, + &rngOffsets, &aziOffsets); // an array for the computed interferogram std::valarray> data(width*length); From 8ae93ae7ca10a286c8560a0f3a32b9edc2b4b898 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Thu, 14 Dec 2023 22:58:51 +0000 Subject: [PATCH 094/106] minors --- cxx/isce3/signal/Crossmul.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 2fea120b8..89ace0df5 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -605,10 +605,13 @@ crossmul(isce3::io::Raster& refSlcRaster, // upsampled block of secondary SLC std::valarray> secSlcUpsampled; - // only resize valarrays and init FFT when oversampling - if (_oversampleFactor > 1) { + if ((_oversampleFactor > 1) || _doCommonRangeBandFilter) { refSpectrum.resize(spectrumSize); secSpectrum.resize(spectrumSize); + } + + // only resize valarrays and init FFT when oversampling + if (_oversampleFactor > 1) { refSpectrumUpsampled.resize(spectrumUpsampleSize); secSpectrumUpsampled.resize(spectrumUpsampleSize); @@ -651,9 +654,6 @@ crossmul(isce3::io::Raster& refSlcRaster, if (_doCommonRangeBandFilter) { geometryIfgram.resize(spectrumSize); - refSpectrum.resize(spectrumSize); - secSpectrum.resize(spectrumSize); - rangeFrequencies.resize(fft_size); // Compute the range frequency for each pixel From 3a0f2a9a25a325e1bb0559210a96a528f771998e Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Fri, 15 Dec 2023 06:08:09 +0000 Subject: [PATCH 095/106] fix the complex sinc and modify the kaiser function --- cxx/isce3/math/Sinc.h | 5 +++++ cxx/isce3/math/Sinc.icc | 25 +++++++++++++++++++++++++ cxx/isce3/product/RadarGridProduct.h | 14 +++++++------- cxx/isce3/signal/Crossmul.cpp | 26 +++++++++++++------------- cxx/isce3/signal/Filter.cpp | 19 ++++++++++++------- tests/cxx/isce3/signal/filter.cpp | 6 +++--- 6 files changed, 65 insertions(+), 30 deletions(-) diff --git a/cxx/isce3/math/Sinc.h b/cxx/isce3/math/Sinc.h index a1ef33fd3..ee4161fe9 100644 --- a/cxx/isce3/math/Sinc.h +++ b/cxx/isce3/math/Sinc.h @@ -1,10 +1,15 @@ #pragma once #include +#include namespace isce3 { namespace math { /** sinc function defined as \f$ \frac{\sin(\pi x)}{\pi x} \f$ */ +template +CUDA_HOSTDEV +std::complex sinc(std::complex t); + template CUDA_HOSTDEV T sinc(T t); diff --git a/cxx/isce3/math/Sinc.icc b/cxx/isce3/math/Sinc.icc index c2a4e67a2..1864c3a5e 100644 --- a/cxx/isce3/math/Sinc.icc +++ b/cxx/isce3/math/Sinc.icc @@ -90,4 +90,29 @@ T sinc(T t) return std::sin(x) / x; } +template +CUDA_HOSTDEV +inline +std::complex sinc(std::complex t) +{ + static_assert(std::is_floating_point::value); + + using U = typename std::remove_cv::type; + static constexpr auto eps1 = detail::root_epsilon(); + static constexpr auto eps2 = detail::fourth_root_epsilon(); + + auto u = T(M_PI) * t; + auto x = std::abs(u); + + // approximate by Taylor series expansion near zero + if (x < eps2) { + std::complex out = static_cast(1); + if (x > eps1) { + out -= u * u / static_cast(6); + } + return out; + } + return std::sin(u) / u; +} + }} diff --git a/cxx/isce3/product/RadarGridProduct.h b/cxx/isce3/product/RadarGridProduct.h index 1802b6bda..860cc9597 100644 --- a/cxx/isce3/product/RadarGridProduct.h +++ b/cxx/isce3/product/RadarGridProduct.h @@ -27,7 +27,7 @@ namespace isce3 { namespace product { /** * Return the path to each child group of `group` that ends with the substring * `group_name`. - * + * * \param[in] group Parent group * \param[in] group_name Search string * \returns List of child group paths @@ -39,13 +39,13 @@ std::vector findGroupPath( * Return grids or swaths group paths within the base_group. * Start by assigning an empty string to image_group_str in case * grids and swaths group are not found. - * + * * \param[in] file * \param[in] base_dir Path to `base_group` object (e.g. '/science/') * \param[in] base_group Base group * \param[in] key_vector Vector containing possible image groups * (e.g., 'swaths', 'grids', or both) to look for - * \param[out] image_group_str Path to first image group found containing + * \param[out] image_group_str Path to first image group found containing * one of the `key_vector` keys (e.g., '/science/LSAR/RSLC/swaths') * \param[in] metadata_group_str Path to first metadata group found by * substituting `key` with `metadata` in `image_group_str` @@ -60,10 +60,10 @@ void setImageMetadataGroupStr( std::string &metadata_group_str); /** RadarGridProduct class declaration - * + * * The Produt attribute Swaths map, i.e. _swaths, associates the - * frequency (key) with the Swath object (value). The RadarGridProduct object - * is usually initiated with an empty map and the serialization of + * frequency (key) with the Swath object (value). The RadarGridProduct object + * is usually initiated with an empty map and the serialization of * the SAR product is responsible for populating the Swath map * from the product's metadata. * @@ -75,7 +75,7 @@ class RadarGridProduct { RadarGridProduct(isce3::io::IH5File &); /** Constructor with Metadata and Swath map. */ inline RadarGridProduct(const Metadata &, const std::map &); - + /** Get a read-only reference to the metadata */ inline const Metadata & metadata() const { return _metadata; } /** Get a reference to the metadata. */ diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 89ace0df5..cd510c228 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -213,8 +213,8 @@ azimuthCommonBandFilter(std::valarray> &refSlc, } /** -* @param[in] refDopplerCentroids doppler centroid frequency for reference -* @param[in] secDopplerCentroids doppler centroid frequency for secondary +* @param[in] refDopplerCentroids doppler centroid frequency for reference, w.r.t slant range +* @param[in] secDopplerCentroids doppler centroid frequency for secondary, w.r.t slant range * @param[in] numOfDopplerCentroids number of valid doppler centroids * @param[in] bandwidth intput SLCs bandwidth * @param[in] prf pulse repeat frequency @@ -243,12 +243,14 @@ isce3::signal::Crossmul::_computeMaxAzimuthFilterKernelSize(std::valarray +#include /** * @param[in] signal a block of data to filter @@ -316,7 +317,6 @@ constructRangeCommonBandKaiserFilter(const double subBandCenterFrequency, std::valarray>& filter1D, const int maxFilterKernelSize) { - if (filter1D.size() <= 0) filter1D.resize(fft_size); filter1D = std::complex(0.0, 0.0); @@ -460,7 +460,7 @@ constructAzimuthCommonBandFilter(const std::valarray & refDoppler, prf, windowParameter, ncols, nrows); } - + std::string err_str = filterType + " filter has not been implemented"; pyre::journal::error_t err( "isce.signal.Filter.constructAzimuthCommonBandFilter"); @@ -823,8 +823,9 @@ isce3::signal::Filter::_kaiser_irf(const std::valarray &t, if (irf.size() <= 0) irf.resize(t.size()); for (size_t i = 0; i < t.size(); i++) { - std::complex val(t[i] * t[i] - alpha * alpha, 0.0); - irf[i] = std::complex(isce3::math::sinc(std::sqrt(val).real()) / beta0, 0.0); + auto val = std::complex(t[i] * t[i] - alpha * alpha, 0.0); + auto sincVal = isce3::math::complex_operations::operator/(isce3::math::sinc(std::sqrt(val)),beta0); + irf[i] = std::complex(sincVal.real(), 0.0); } } @@ -838,10 +839,14 @@ isce3::signal::Filter::_kaiser(const int n, if (coeffs.size() <= 0) coeffs.resize(n); + if (n == 1) { + coeffs[0] = std::complex(1.0,0.0); + return; + } + const double alpha = (n - 1) / 2.0; for (size_t i = 0; i < n; i++) { - const double t = i - (n - 1) / 2.0; - if (std::abs(t) <= n / 2.0) coeffs[i] = isce3::math::bessel_i0( - beta * std::sqrt(1.0 - (2 * t / (n - 1)) * (2 * t / (n - 1)))) / beta0; + const double t = (i - alpha)/alpha; + coeffs[i] = isce3::math::bessel_i0(beta * std::sqrt(1.0 - t * t)) / beta0; } } diff --git a/tests/cxx/isce3/signal/filter.cpp b/tests/cxx/isce3/signal/filter.cpp index 1967a260c..7a66f4a43 100644 --- a/tests/cxx/isce3/signal/filter.cpp +++ b/tests/cxx/isce3/signal/filter.cpp @@ -135,9 +135,9 @@ TEST(Filter, constructRangeCommonBandKaiserFilter) 1.6, kaiser); - ASSERT_LT(std::abs(std::abs(kaiser[0]) - 0.768964), 1.0e-6); - ASSERT_LT(std::abs(std::abs(kaiser[127]) - 0.234426), 1.0e-6); - ASSERT_LT(std::abs(std::abs(kaiser[255]) - 0.768879), 1.0e-6); + ASSERT_LT(std::abs(std::abs(kaiser[0]) - 0.9997906684875488), 1.0e-6); + ASSERT_LT(std::abs(std::abs(kaiser[127]) - 0.003600120544433594), 1.0e-6); + ASSERT_LT(std::abs(std::abs(kaiser[255]) - 0.99970543384552), 1.0e-6); } int main(int argc, char * argv[]) { From 2cde47635ea499508befc1861043a2ee04ccfe84 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Fri, 15 Dec 2023 06:18:29 +0000 Subject: [PATCH 096/106] operator overload import --- cxx/isce3/signal/Filter.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index fd24bd7f4..49b1e0617 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -8,6 +8,7 @@ #include "Filter.h" #include #include +using namespace isce3::math::complex_operations; /** * @param[in] signal a block of data to filter @@ -824,7 +825,7 @@ isce3::signal::Filter::_kaiser_irf(const std::valarray &t, if (irf.size() <= 0) irf.resize(t.size()); for (size_t i = 0; i < t.size(); i++) { auto val = std::complex(t[i] * t[i] - alpha * alpha, 0.0); - auto sincVal = isce3::math::complex_operations::operator/(isce3::math::sinc(std::sqrt(val)),beta0); + auto sincVal = isce3::math::sinc(std::sqrt(val)) / beta0; irf[i] = std::complex(sincVal.real(), 0.0); } } @@ -905,7 +906,7 @@ isce3::signal::Filter::_design_shaped_lowpass_filter(const double bandwidth, if (kaiser_window.size() <= 0) kaiser_window.resize(n); for (size_t i = 0; i < n; i++) { - kaiser_window[i] = std::complex(bw, 0.0) * irf[i] * kaiser[i]; + kaiser_window[i] = irf[i] * kaiser[i] * bw; } } From 4779dba4f49f6efb19ef6bd349097c01e9ac18a2 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Fri, 15 Dec 2023 06:28:25 +0000 Subject: [PATCH 097/106] remove the product.swath(freq) --- cxx/isce3/signal/Filter.cpp | 8 +++--- cxx/isce3/signal/Filter.h | 2 +- python/packages/nisar/workflows/crossmul.py | 3 ++- tests/cxx/isce3/signal/crossmul.cpp | 30 +++++++++++---------- tests/cxx/isce3/signal/filter.cpp | 5 ++-- 5 files changed, 25 insertions(+), 23 deletions(-) diff --git a/cxx/isce3/signal/Filter.cpp b/cxx/isce3/signal/Filter.cpp index 49b1e0617..df8df22c1 100644 --- a/cxx/isce3/signal/Filter.cpp +++ b/cxx/isce3/signal/Filter.cpp @@ -858,7 +858,7 @@ isce3::signal::Filter::_lowpass2bandpass(const std::valarray> std::valarray> &band_pass_filter) { if (band_pass_filter.size() <= 0) band_pass_filter.resize(low_pass_filter.size()); - const int n = low_pass_filter.size(); + const size_t n = low_pass_filter.size(); for (size_t i = 0; i < n; i++) { const double t = (i - (n - 1) / 2.0); const double phase = 2.0 * M_PI * fc * t; @@ -872,7 +872,7 @@ void isce3::signal::Filter::_design_shaped_lowpass_filter(const double bandwidth, const double fs, const double window_shape, - std::valarray> &kaiser_window, + std::valarray> &coeffs, const double stopatt, const double transition_width, const bool force_odd_len) @@ -903,10 +903,10 @@ isce3::signal::Filter::_design_shaped_lowpass_filter(const double bandwidth, _kaiser_irf(t * bw, window_shape, irf); _kaiser(n, beta, kaiser); - if (kaiser_window.size() <= 0) kaiser_window.resize(n); + if (coeffs.size() <= 0) coeffs.resize(n); for (size_t i = 0; i < n; i++) { - kaiser_window[i] = irf[i] * kaiser[i] * bw; + coeffs[i] = irf[i] * kaiser[i] * bw; } } diff --git a/cxx/isce3/signal/Filter.h b/cxx/isce3/signal/Filter.h index f3bb10a1f..80714f0ce 100644 --- a/cxx/isce3/signal/Filter.h +++ b/cxx/isce3/signal/Filter.h @@ -226,7 +226,7 @@ class isce3::signal::Filter { void _design_shaped_lowpass_filter(const double bandwidth, const double fs, const double window_shape, - std::valarray> &kaiser_window, + std::valarray> &coeffs, const double stopatt = 40.0, const double transition_width = 0.15, const bool force_odd_len = false); diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index 2e89888f0..9b0c3be1a 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -212,7 +212,8 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', # populate the new bandwidth along azimuth and range after the common band filter # if there is no common band filter applied, the bandwith will remain the same with - # the orignal SLC bandwidth + # the orignal SLC bandwidth. + # NOTE: Those bandwidths have already been in the dataset. # TODO: GPU if not use_gpu: processing_info_path = \ diff --git a/tests/cxx/isce3/signal/crossmul.cpp b/tests/cxx/isce3/signal/crossmul.cpp index 9974b6116..82c84af73 100644 --- a/tests/cxx/isce3/signal/crossmul.cpp +++ b/tests/cxx/isce3/signal/crossmul.cpp @@ -54,6 +54,7 @@ TEST(Crossmul, RunCrossmul) // get the Doppler for refernce SLC const char freq = 'A'; isce3::core::LUT2d dop1 = product.metadata().procInfo().dopplerCentroid(freq); + auto swath = product.swath(freq); // Since this test careates an interferogram between the refernce SLC and itself, // the second Doppler is the same as the first @@ -72,13 +73,13 @@ TEST(Crossmul, RunCrossmul) crsmul.azimuthLooks(1); // set the product information for the common band filtering and flattenning - const double wavelength = product.swath(freq).processedWavelength(); - const double azimuthBandwidth = product.swath(freq).processedAzimuthBandwidth(); - const double rangeBandwidth = product.swath(freq).processedRangeBandwidth(); - const double prf = product.swath(freq).nominalAcquisitionPRF(); - const double rngPixelSampling = product.swath(freq).rangePixelSpacing(); - const double startAzimuthTime = product.swath(freq).zeroDopplerTime()[0]; - const double startSlantRange = product.swath(freq).slantRange()[0]; + const double wavelength = swath.processedWavelength(); + const double azimuthBandwidth = swath.processedAzimuthBandwidth(); + const double rangeBandwidth = swath.processedRangeBandwidth(); + const double prf = swath.nominalAcquisitionPRF(); + const double rngPixelSampling = swath.rangePixelSpacing(); + const double startAzimuthTime = swath.zeroDopplerTime()[0]; + const double startSlantRange = swath.slantRange()[0]; crsmul.wavelength(wavelength); crsmul.prf(prf); @@ -159,6 +160,7 @@ TEST(Crossmul, RunCrossmulMLook) // get the Doppler polynomial for refernce SLC const char freq = 'A'; isce3::core::LUT2d dop1 = product.metadata().procInfo().dopplerCentroid(freq); + auto swath = product.swath(freq); // Since this test careates an interferogram between the refernce SLC and itself, // the second Doppler is the same as the first @@ -177,13 +179,13 @@ TEST(Crossmul, RunCrossmulMLook) crsmul.azimuthLooks(azLooks); // set the product information for the common band filtering and flattenning - const double wavelength = product.swath(freq).processedWavelength(); - const double azimuthBandwidth = product.swath(freq).processedAzimuthBandwidth(); - const double rangeBandwidth = product.swath(freq).processedRangeBandwidth(); - const double prf = product.swath(freq).nominalAcquisitionPRF(); - const double rngPixelSampling = product.swath(freq).rangePixelSpacing(); - const double startAzimuthTime = product.swath(freq).zeroDopplerTime()[0]; - const double startSlantRange = product.swath(freq).slantRange()[0]; + const double wavelength = swath.processedWavelength(); + const double azimuthBandwidth = swath.processedAzimuthBandwidth(); + const double rangeBandwidth = swath.processedRangeBandwidth(); + const double prf = swath.nominalAcquisitionPRF(); + const double rngPixelSampling = swath.rangePixelSpacing(); + const double startAzimuthTime = swath.zeroDopplerTime()[0]; + const double startSlantRange = swath.slantRange()[0]; crsmul.wavelength(wavelength); crsmul.prf(prf); diff --git a/tests/cxx/isce3/signal/filter.cpp b/tests/cxx/isce3/signal/filter.cpp index 7a66f4a43..312344127 100644 --- a/tests/cxx/isce3/signal/filter.cpp +++ b/tests/cxx/isce3/signal/filter.cpp @@ -99,7 +99,7 @@ TEST(Filter, constructBoxcarRangeBandpassFilter) blockRows, filterType); - //filter.writeFilter(ncols, blockRows); + filter.writeFilter(ncols, blockRows); // change the filter type to cosine filterType = "cosine"; @@ -112,8 +112,7 @@ TEST(Filter, constructBoxcarRangeBandpassFilter) blockRows, filterType); - //filter.writeFilter(ncols, blockRows); - + filter.writeFilter(ncols, blockRows); } TEST(Filter, constructRangeCommonBandKaiserFilter) From fd33a6b831861950d318283a4773c4e606d7a8bd Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Fri, 15 Dec 2023 06:32:11 +0000 Subject: [PATCH 098/106] add the crossmul test data in the ReadMe --- tests/data/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/data/README.md b/tests/data/README.md index 5efef574c..c23c60b5d 100644 --- a/tests/data/README.md +++ b/tests/data/README.md @@ -27,6 +27,17 @@ $ md5sum NISAR_ANC_L_PR_FRP_20210114T023357_20200107T200000_20200109T040000.xml To reduce the size of the test data, this file was trimmed to the first ten records to produce `attitude.xml`. +## Crossmul + +- **envisat.h5** + + Simulated NISAR SLC using the envisat data with the image dimenson of 500 by 500. + +- **envisat_offsets.tif** + + The range and azimuth offests of the envisat.h5, and all values are 0. + + ## Orbit Orbit sample data in NISAR format (see JPL D-102253) provided by Paul Ries From 7426d108925d03de405bee1073b0e9915e000b2d Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Fri, 15 Dec 2023 06:34:46 +0000 Subject: [PATCH 099/106] fix docstrings --- python/extensions/pybind_isce3/signal/Crossmul.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/extensions/pybind_isce3/signal/Crossmul.cpp b/python/extensions/pybind_isce3/signal/Crossmul.cpp index 035eb5737..02e6cfccf 100644 --- a/python/extensions/pybind_isce3/signal/Crossmul.cpp +++ b/python/extensions/pybind_isce3/signal/Crossmul.cpp @@ -44,9 +44,10 @@ void addbinding(py::class_ & pyCrossmul) Output interferogram raster coherence: Raster Output coherence raster - interferogram: Raster + range_offset: Raster Optional range offset raster usef for flattening and common band filter - Optional range offset raster usef for azimuth common band filter + azimuth_offset: Raster + Optional azimuth offset raster usef for azimuth common band filter range_bandwidth: float range bandwidth of the reference SLC azimuth_bandwidth: float From e6c0e444581ed574f8557d300757d1f451861dc7 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 19 Dec 2023 18:48:06 +0000 Subject: [PATCH 100/106] add critical secton to compute ref and sec dopp centroids --- cxx/isce3/signal/Crossmul.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index cd510c228..f7b10907f 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -334,9 +334,12 @@ isce3::signal::Crossmul::_computeDoppCentroids(const isce3::core::LUT2d // Interpolate the doppler centroids if (refDoppler.contains(refY, refX) && secDoppler.contains(secY, secX)) { - refDopplerCentroids[col] += refDoppler.eval(refY, refX); - secDopplerCentroids[col] += secDoppler.eval(secY, secX); - numOfValidDopplerCentroids[col]++; + #pragma omp critical + { + refDopplerCentroids[col] += refDoppler.eval(refY, refX); + secDopplerCentroids[col] += secDoppler.eval(secY, secX); + numOfValidDopplerCentroids[col]++; + } } } } @@ -450,13 +453,13 @@ crossmul(isce3::io::Raster& refSlcRaster, debug << "max azimuth window kernel size: " << maxAzimuthFilterKernelSize << pyre::journal::endl; // to ensure the overlap size is an integer multiple number of azimuth looks. - int numOfAzimuthLooks = (maxAzimuthFilterKernelSize + _azimuthLooks - 1) / _azimuthLooks; + int k = (maxAzimuthFilterKernelSize + _azimuthLooks - 1) / _azimuthLooks; // Force the kernel size to be even - numOfAzimuthLooks = (numOfAzimuthLooks % 2 == 0) ? numOfAzimuthLooks : numOfAzimuthLooks + 1; + k = (k % 2 == 0) ? k : k + 1; // The overlap size will be even - overlapSize = numOfAzimuthLooks * _azimuthLooks; + overlapSize = k * _azimuthLooks; halfOverlapSize = overlapSize / 2; // Compute the lines per block to account for the overlaps between two blocks From aa21514697773e7d17f2a8aeef9594e24aabf495 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 19 Dec 2023 20:23:13 +0000 Subject: [PATCH 101/106] openmp for computing the doppler centroids --- cxx/isce3/cuda/signal/gpuCrossMul.h | 4 +++- cxx/isce3/signal/Crossmul.cpp | 35 +++++++++++++---------------- cxx/isce3/signal/Crossmul.h | 8 +++---- 3 files changed, 21 insertions(+), 26 deletions(-) diff --git a/cxx/isce3/cuda/signal/gpuCrossMul.h b/cxx/isce3/cuda/signal/gpuCrossMul.h index 7059e136e..795aa15db 100644 --- a/cxx/isce3/cuda/signal/gpuCrossMul.h +++ b/cxx/isce3/cuda/signal/gpuCrossMul.h @@ -5,7 +5,6 @@ #include #include -#include #include #include @@ -25,6 +24,9 @@ class isce3::cuda::signal::gpuCrossmul { * \param[out] coherenceRaster output coherence raster * \param[in] rngOffsetRaster optional pointer to range offset raster * if provided, interferogram will be flattened + * \param[in] aziOffsetRaster optional pointer to azimuth offset raster + * it is a placeholder here, and will implement the + * azimuth common band filter based on it */ void crossmul(isce3::io::Raster& refSlcRaster, isce3::io::Raster& secSlcRaster, diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index f7b10907f..3a258a884 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -3,7 +3,9 @@ #include "Filter.h" #include "Looks.h" #include "Signal.h" + #include +#include /** * Compute the frequency response due to a subpixel shift introduced by @@ -223,9 +225,9 @@ azimuthCommonBandFilter(std::valarray> &refSlc, * @returns the maximum azimuth filter kernel size */ int -isce3::signal::Crossmul::_computeMaxAzimuthFilterKernelSize(std::valarray &refDopplerCentroids, - std::valarray &secDopplerCentroids, - std::valarray &numOfValidDopplerCentroids, +isce3::signal::Crossmul::_computeMaxAzimuthFilterKernelSize(const std::valarray &refDopplerCentroids, + const std::valarray &secDopplerCentroids, + const std::valarray &numOfValidDopplerCentroids, const double bandwidth, const double prf, const double beta, @@ -310,20 +312,16 @@ isce3::signal::Crossmul::_computeDoppCentroids(const isce3::core::LUT2d numOfValidDopplerCentroids = 0; } + std::valarray rangeOffsets(ncols); + std::valarray azimuthOffsets(ncols); + // Compute the doppler centroids for the reference and secondary images - #pragma omp parallel for for (size_t row = 0; row < nrows; row++) { - // Private variables for each thread - std::valarray rangeOffsets(ncols); - std::valarray azimuthOffsets(ncols); - - // Read the data thread by thread - #pragma omp critical - { - rngOffsetRaster->getLine(rangeOffsets, row); - aziOffsetRaster->getLine(azimuthOffsets, row); - } + rngOffsetRaster->getLine(rangeOffsets, row); + aziOffsetRaster->getLine(azimuthOffsets, row); + + #pragma omp parallel for for (size_t col = 0; col < ncols; col++) { // Convert the line/pixel to range doppler coordinates double refX = col * rangePixelSpacing() + refStartRange(); @@ -334,12 +332,9 @@ isce3::signal::Crossmul::_computeDoppCentroids(const isce3::core::LUT2d // Interpolate the doppler centroids if (refDoppler.contains(refY, refX) && secDoppler.contains(secY, secX)) { - #pragma omp critical - { - refDopplerCentroids[col] += refDoppler.eval(refY, refX); - secDopplerCentroids[col] += secDoppler.eval(secY, secX); - numOfValidDopplerCentroids[col]++; - } + refDopplerCentroids[col] += refDoppler.eval(refY, refX); + secDopplerCentroids[col] += secDoppler.eval(secY, secX); + numOfValidDopplerCentroids[col]++; } } } diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 7dfd5eda3..ee5595931 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -4,11 +4,9 @@ #include #include -#include #include #include #include -#include /** \brief Intereferogram generation by cross-multiplication of reference and secondary SLCs. * @@ -237,9 +235,9 @@ class isce3::signal::Crossmul { std::valarray &secDopplerCentroids, std::valarray &numOfValidDopplerCentroids); - int _computeMaxAzimuthFilterKernelSize(std::valarray &refDopplerCentroids, - std::valarray &secDopplerCentroids, - std::valarray &numOfValidDopplerCentroids, + int _computeMaxAzimuthFilterKernelSize(const std::valarray &refDopplerCentroids, + const std::valarray &secDopplerCentroids, + const std::valarray &numOfValidDopplerCentroids, const double bandwidth, const double prf, const double beta, From 7142cd68e4452cdeb7804dc83a9d4a8fbe75392f Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 19 Dec 2023 20:24:57 +0000 Subject: [PATCH 102/106] docstrings --- cxx/isce3/signal/Crossmul.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index ee5595931..016a9794e 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -320,10 +320,12 @@ class isce3::signal::Crossmul { // minimum range spectrum overlap fraction between reference and secondary RSLC double _minRangeSpectrumOverlapFraction = 0.2; - // ripple for the FIR filter + // maximum stop band ripple amplitude, + // in dB below the pass band gain, for the FIR filter double _ripple = 40.0; - // transition width + // transition width of the common band filter(s), + // relative to the pass band width (total width of both transition bands) double _transitionWidth = 0.15; }; From 00e96d46855b1bee36c6da2254f51f5d8056c108 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Tue, 19 Dec 2023 20:33:12 +0000 Subject: [PATCH 103/106] init the max range filter kernel size 0 --- cxx/isce3/signal/Crossmul.cpp | 6 ++---- cxx/isce3/signal/Crossmul.h | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index 3a258a884..babf30960 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -230,7 +230,6 @@ isce3::signal::Crossmul::_computeMaxAzimuthFilterKernelSize(const std::valarray< const std::valarray &numOfValidDopplerCentroids, const double bandwidth, const double prf, - const double beta, isce3::signal::Filter &aziFilter) { int max_kernel_size = 0; @@ -390,7 +389,7 @@ crossmul(isce3::io::Raster& refSlcRaster, "interferogram and coherence rasters width do not match"); // maximum range filter kernel size - size_t maxRangeFilterKernelSize = 256; + size_t maxRangeFilterKernelSize = 0; // Compute the range sampling frequency in Hz using the range pixel spacing _rangeSamplingFrequency = 1.0 / (_rangePixelSpacing*2.0/isce3::core::speed_of_light); @@ -412,7 +411,7 @@ crossmul(isce3::io::Raster& refSlcRaster, throw isce3::except::LengthError(ISCE_SRCINFO(), "_oversampleFactor * fft_size > INT_MAX"); // force the multilook to be true if azimuth or range looks > 1 - _multiLookEnabled = ((_rangeLooks > 1) || (_azimuthLooks > 1)) ? true : false; + _multiLookEnabled = ((_rangeLooks > 1) || (_azimuthLooks > 1)); // Declare valarray for range and azimuth doppler centroids used by filter std::valarray refDoppCentroids; @@ -442,7 +441,6 @@ crossmul(isce3::io::Raster& refSlcRaster, numOfValidDoppCentroids, _azimuthBandwidth, _prf, - _windowParameter, azimuthFilter); debug << "max azimuth window kernel size: " << maxAzimuthFilterKernelSize diff --git a/cxx/isce3/signal/Crossmul.h b/cxx/isce3/signal/Crossmul.h index 016a9794e..1649365eb 100644 --- a/cxx/isce3/signal/Crossmul.h +++ b/cxx/isce3/signal/Crossmul.h @@ -240,7 +240,6 @@ class isce3::signal::Crossmul { const std::valarray &numOfValidDopplerCentroids, const double bandwidth, const double prf, - const double beta, isce3::signal::Filter &aziFilter); //Doppler LUT for the refernce SLC From 92209632065effa090c1717c3c652fba1742b964 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 4 Mar 2024 23:29:25 +0000 Subject: [PATCH 104/106] fix the crossmul --- python/packages/nisar/workflows/crossmul.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/packages/nisar/workflows/crossmul.py b/python/packages/nisar/workflows/crossmul.py index 473db31be..a469ef8e1 100644 --- a/python/packages/nisar/workflows/crossmul.py +++ b/python/packages/nisar/workflows/crossmul.py @@ -129,12 +129,12 @@ def run(cfg: dict, output_hdf5: str = None, resample_type='coarse', # azimuth band width and PRF crossmul.azimuth_bandwidth = \ ref_slc.getSwathMetadata(freq).processed_azimuth_bandwidth - crossmul.prf = rdr_grid.prf + crossmul.prf = ref_radar_grid.prf # start range and azimuth time for reference and secondary images - crossmul.ref_start_range = rdr_grid.starting_range + crossmul.ref_start_range = ref_radar_grid.starting_range crossmul.sec_start_range = sec_rdr_grid.starting_range - crossmul.ref_start_azimuth_time = rdr_grid.sensing_start + crossmul.ref_start_azimuth_time = ref_radar_grid.sensing_start crossmul.sec_start_azimuth_time = sec_rdr_grid.sensing_start # enable/disable flatten accordingly From 73804d1aa10f0f937e1953c07131556b195eaebe Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Mon, 11 Mar 2024 21:40:30 +0000 Subject: [PATCH 105/106] fix typos --- cxx/isce3/signal/Crossmul.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cxx/isce3/signal/Crossmul.cpp b/cxx/isce3/signal/Crossmul.cpp index b54396a9a..68a1acbf9 100644 --- a/cxx/isce3/signal/Crossmul.cpp +++ b/cxx/isce3/signal/Crossmul.cpp @@ -35,7 +35,7 @@ void lookdownShiftImpact(size_t oversample, size_t fft_size, size_t blockRows, // As an example for a signal with length of 5 and : // original sample locations: 0 1 2 3 4 // upsampled sample locations: 0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 - // Looked dow sample locations: 0.25 1.25 2.25 3.25 4.25 + // Looked down sample locations: 0.25 1.25 2.25 3.25 4.25 // Obviously the signal after looking down would be shifted by 0.25 pixel in // range comared to the original signal. Since a shift in time domain introduces // a linear phase in frequency domain, we compute the impact in frequency domain. From ef22ba0143aab235ef934873ced364bc90344a66 Mon Sep 17 00:00:00 2001 From: Xiaodong Huang Date: Wed, 3 Jul 2024 22:33:24 +0000 Subject: [PATCH 106/106] fix the crossmul doppler function --- cxx/isce3/cuda/signal/gpuCrossMul.cu | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/cxx/isce3/cuda/signal/gpuCrossMul.cu b/cxx/isce3/cuda/signal/gpuCrossMul.cu index 78d1ccae3..3a3a65575 100644 --- a/cxx/isce3/cuda/signal/gpuCrossMul.cu +++ b/cxx/isce3/cuda/signal/gpuCrossMul.cu @@ -119,8 +119,7 @@ __global__ void flatten_g(thrust::complex *ifg, /** Set number of range looks */ -void -gpuCrossmul::rangeLooks(int rngLks) { +void gpuCrossmul::rangeLooks(int rngLks) { if (rngLks < 1) { std::string error_msg = "ERROR CUDA crossmul range multilook < 1"; throw isce3::except::InvalidArgument(ISCE_SRCINFO(), error_msg); @@ -134,8 +133,7 @@ gpuCrossmul::rangeLooks(int rngLks) { } /** Set number of azimuth looks */ -void -gpuCrossmul::azimuthLooks(int azLks) { +void gpuCrossmul::azimuthLooks(int azLks) { if (azLks < 1) { std::string error_msg = "ERROR CUDA crossmul azimuth multilook < 1"; throw isce3::except::InvalidArgument(ISCE_SRCINFO(), error_msg); @@ -148,9 +146,8 @@ gpuCrossmul::azimuthLooks(int azLks) { _multiLookEnabled = false; } -void -gpuCrossmul::doppler(isce3::core::LUT1d refDoppler, - isce3::core::LUT1d secDoppler) +void gpuCrossmul::doppler(isce3::core::LUT2d refDoppler, + isce3::core::LUT2d secDoppler) { _refDoppler = refDoppler; _secDoppler = secDoppler;