-
Notifications
You must be signed in to change notification settings - Fork 298
Pycuampcor v2 #922
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Pycuampcor v2 #922
Conversation
in this update, * either the starting pixel(corner) or the center of window location may be specified (see README) * by specifying the starting/ending pixel locations, the reference/search window may go beyond the range of the original images. Zeros are filled in instead. In this case, the offset fields at the edge may be incorrect. * The range check is no longer needed. It only runs in DEBUG mode and issues warning messages when pixels are outside the image range.
…tional approach to side Nyquist frequency (N/2) with negative frequency
…virtual class for different workflows
…ing back Sinc Oversampler
|
Thank you @lijun99 for this extensive PR. Based on our offline discussions I'm aware of most of developments in this PR. However, for clarity and to help the user community following this repository would you please update the description of the PR and provide some explanation in few bullets summarizing the changes that comes in this PR. |
vbrancat
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lijun99 Thank you for this PR! It’s very exciting, and I’m eager to test it. I will leave some further comments after I am done with the testing.
In the meantime, I’ve added some comments and questions on the code. Since I’m not a CUDA programmer, I’ll leave it to @gmgunter and @rtburns-jpl to weigh in on the CUDA-specific parts. Overall, the PR looks great to me, but there are a few comments and considerations that I think need to be addressed:
-
I’m not a fan of the ROIPAC vs. GRiMP terminology, as I believe most users won’t be familiar with it either. At a high level (e.g., in the Python interface), we should frame this in terms of enabling or disabling anti-aliasing oversampling and provide a clear explanation of the advantages and disadvantages of each option. This approach would ensure complete transparency for users.
-
It’s unclear to me how offset estimates are handled near the edges. For instance, if we’re at the edge of the search window, do we use zero-padding? Could you point me to the part of the code where this logic is implemented?
-
I noticed that the code internally includes a threshold on the SNR, but it’s unclear to me if this option is actively used. Additionally, this threshold is not exposed to users. Could you clarify its purpose and usage?
| cuDenseOffsets.py --reference $reference --secondary $secondary --ww $ww --wh $wh --sw $sw --sh $sh \ | ||
| --mm $mm --kw $kw --kh $kh --gross $gross --rr $rgshift --aa $azshift --oo $oo \ | ||
| --deramp $deramp --outprefix $outprefix --outsuffix $outsuffix \ | ||
| --gpuid $gpuid --usemmap $usemmap --mmapsize $mmapsize \ | ||
| --nwac $nwac --nwdc $nwdc --workflow $workflow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the flag used to switch between the old PyCuAmpcor implementation (i.e., the one following the Fortran code) and the new v2 implementation exposed to the user? If it is, it would be helpful to add it here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added.
| parser.add_argument('--startpixeldw', dest='startpixeldw', type=int, default=None, | ||
| help='Starting Pixel down of the reference image.' + | ||
| 'Default: %(default)s to be determined by margin and search range.') | ||
| 'Default: %(default)s to use the first pixel.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not understand this. Can you really start from the first pixel if this parameter has not been assigned? Don't you still need a margin equal to the search window?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is to fix the location of the reference window, for cases to compare results with different window sizes and search ranges. It could lead to out-of-range issues for windows at the edges. Zeros are padded to keep the program running. Warnings are raised to users to alert them of the inaccuracy of these results.
| parser.add_argument('--wf', '--workflow', dest='workflow', type=int, default=0, | ||
| help='workflow (0 = ROIPAC, 1 = GrIMP) (default: %(default)s).') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we include this flag in the example? The original Ampcor followed the GRIMP approach but later evolved into the ROIPAC algorithm for computational efficiency. To ensure transparency for users unfamiliar with GRIMP and ROIPAC, we should reframe this in terms of enabling or disabling 2x anti-aliasing oversampling for integer offset detection. Additionally, the help guide should clarify the implications of using or not using 2x oversampling to help users make informed decisions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
| if inps.use_center != 0: | ||
| # the given starting coordinate is the center, adjust it | ||
| startPixelDown -= inps.winhgt//2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that PyCuAmpcor uses the top-left corner of a pixel as the reference point (origin) for its pixel coordinates. If this assumption is correct, then to calculate the center of a window relative to its top-left corner, you would need to add half of the window size (in both height and width) to the top-left coordinate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Explained earlier.
| # use margin + halfSearchHeight instead | ||
| startPixelDown = margin + inps.srchgt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sort of contradicts what you have written in the help i.e., using the first pixel
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
explained earlier.
| // correlation surface | ||
| int2 corrWindowSize; // 2*halfSearchRange + 1 | ||
| int2 corrZoomInSize; // zoomWindowSize+1 | ||
| int2 corrZoomInOversampledSize; // corrZoomInSize * oversamplingFactor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit-picking. Since we have multiple stages of oversampling, can we specify which oversampling factor are we referring to here? I assume this refers to the cross-correlation surface oversampling factor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed.
| int2 corrZoomInSize; // zoomWindowSize+1 | ||
| int2 corrZoomInOversampledSize; // corrZoomInSize * oversamplingFactor | ||
|
|
||
| int corrStatWindowSize; ///< correlation surface size used to estimate snr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| int corrStatWindowSize; ///< correlation surface size used to estimate snr | |
| int corrStatWindowSize; ///< correlation surface size used to estimate correlation surface statistics (e.g., peak SNR, covariance matrix) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
covariance only needs a few pixels around the peak. The statement was correct.
|
|
||
| int corrStatWindowSize; ///< correlation surface size used to estimate snr | ||
|
|
||
| float thresholdSNR; ///< Threshold of Signal noise ratio to remove noisy data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that PyCuAmpcor computes each offset independently of its associated statistics. If this is correct, why is there a threshold on the SNR? Although this threshold is not exposed to users, what would happen if it were? Does PyCuAmpcor skip the computation of the sub-pixel offset for estimates with an SNR below the threshold? SNR is an unreliable metric for assessing the quality of offset estimates. If outlier removal is necessary, I recommend using the covariance matrix as a more robust alternative.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deleted. PyCuAmpcor leaves filtering, cullings for users.
| std::string offsetImageName; ///< Offset fields output filename | ||
| std::string snrImageName; ///< Output SNR filename | ||
| std::string covImageName; ///< Output variance filename | ||
| std::string peakValueImageName; ///< Output correlation surface peak value filename |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| std::string peakValueImageName; ///< Output correlation surface peak value filename | |
| std::string peakValueImageName; ///< Output normalized correlation surface peak value filename |
Let's specify that is normalized, otherwise the use of this metric is meaningless
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed.
| covValue[idxImage] = make_float3(99.0, 99.0, 0.0); | ||
| covValue[idxImage] = make_real3(99.0, 99.0, 0.0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To my understanding, if the Gaussian curvature is too small (less than 0.01) then we assign a noData value of 99. Why we do this and where is the threshold of 0.01 come from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This follows the ROIPAC. We could make it a user configurable parameter.
|
@lijun99 Thank you for adding the PR description. We see that one big change contributing to the big PR is the functionality to build the code with both single/double precision. Since our tests have not demonstrated a meaningful difference for the offsets results with the two builds, we are a bit hesitant if we should go that way. Or at least we are not sure if the implementation approach for adding double precision is the most efficient way. Are you open to: 1- remove double precision build from this PR. We expect that would significantly reduce the number of lines of codes in this PR |
| # offset and its geometry | ||
| # tip: re-run with --full/out-geom and without --redo to generate geometry only | ||
| cuDenseOffsets.py -r ./SLC/20151120/20151120.slc.full -s ./SLC/20151214/20151214.slc.full --outprefix ./offsets/20151120_20151214/offset --ww 256 --wh 256 --sw 8 --sh 8 --oo 32 --kw 300 --kh 100 --nwac 100 --nwdc 1 --gpuid 2 --full-geom ./geom_reference --out-geom ./offset/geom_reference | ||
| cuDenseOffsets.py -r ./SLC/20151120/20151120.slc.full -s ./SLC/20151214/20151214.slc.full --outprefix ./offsets/20151120_20151214/offset --ww 256 --wh 256 --sw 8 --sh 8 --oo 32 --kw 300 --kh 100 --nwac 100 --nwdc 1 --gpuid 0 --full-geom ./geom_reference --out-geom ./offset/geom_reference |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not able to comment to the exact part of the code but the current help does not contain all the deramping options i.e.,
0: no-deramping, use magnitude for oversampling
1: oversample complex patches and deramp with linear ramp
2: no-deramping, use complex data for oversampling
Can you update the command line function and the help accordingly? Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
…umber of NCC passes
…f the oversampled correlation surface
…d to be a factor of #SMs
…the warnings generated by -Wreorder
+ self.workflow either 0 (old two-step) or 1 (new one-step) + update this option for both cpu and gpu function + add workflow keyword into applications.topsApp.TopsInSAR
4638b1a to
7acaf20
Compare
…for correlation peak values
|
I have merged all the pycuampcor updates to a separate repo, which can be embedded as a submodule in isce2/isce3: here is an example. @rtburns-jpl , please let me know whether this is what you prefer. ( I have renamed the module in lower cases, per the conda requirement). |
PyCuAmpcor Version 2 introduces a new workflow inspired by GrIMP/SpeckleSource, in addition to the original ROIPAC/ampcor workflow. Below is an overview of the new workflow and additional improvements:
Key Features of the New GrIMP/SpeckleSource Workflow:
The GrIMP/SpeckleSource workflow may be slower than ROIPAC/ampcor due to increased computational demands.
However, it may improve accuracy in scenarios with low signal-to-noise ratio (SNR). More details on the workflows and how to choose can be found at contrib/PyCuAmpcor/README.md.
Other Improvements