-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
GDAL Warp behavior when facing NoDataValue in the multigrid-GTG transformation grid #11650
Comments
I would not call the current behavior (to keep the original heights) as a bug. I would post-process the result for example with gdal_calc https://gdal.org/en/stable/programs/gdal_calc.html#gdal-calc. Copy the pixels from the target image, except write nodata where the transformation grid has nodata. Alternatively update the target image with gdal_rasterize https://gdal.org/en/stable/programs/gdal_rasterize.html. Convert the nodata areas first into polygons and then burn nodata value into the pixels which are covered by the polygons. Questions should go to the gdal-dev mailing list at https://lists.osgeo.org/mailman/listinfo/gdal-dev or other support forums such as https://gis.stackexchange.com/. GitHub issues are for bug reports and suggestions for new features. |
The GTG behavior is expected to be different from single resolution transformation grids? A transformation to a new file with single resolution transformation grid results in no data in the areas where there is no transformation. This is why we thought this might be a bug. The user may not be aware of the type of transformation grid used by a pipeline and thus would not expect differing results requiring further postprocessing. |
Sorry, I notice that I wrote my opinions about a thing that I do not understand. Especially I did not notice the different behavior with multiresolution vs. single resolution grids. Reopening. If I read the documentation https://proj.org/en/stable/specifications/geodetictiffgrids.html correctly, Proj should always use the highest resolution grids
|
No worries! We appreciate your engagement. The note from PROJ is what made us think that if a nodata value is returned from the transformation GTG the resulting transformation should also be nodata for a new file, similar to a single resolution grid. |
I may not understand the tiffinfo output right, but maybe the higher-resolution grids are first, not last. What do you think? |
Hello, Agreed, the highest res grids are used and we wrote a pre-processor that takes data from the lower res and inserts it to the higher res as needed. That part works fine. This issue should be independent of the resolution order since there is a nodata value in all three underlying grids and yet we still get an output value (like -39 from the original raster) at those positions unlike if the grid_transform file is a single res tiff then we get a nodata value at that position. |
More a PROJ issue (or feature) than a GDAL one. There's a strong ambiguity in the community of use of PROJ:
PROJ defaults tend to serve more the former than the later. So what you get by default is:
PROJ does notice that the grid evaluates to nodata, and thus fallbacks to using the ballpark operation that does not vertical shift. you can likely get the result you want by setting the PROJ_ONLY_BEST_DEFAULT=YES environment variable (environment variable, not GDAL configuration option), or by setting "only_best_default=on" in PROJ's proj.ini file (cf https://proj.org/en/stable/resource_files.html#proj-ini)
I didn't check how gdalwarp behaved given your reproducer lacks a bit the exact argument used to invoke it, but hopefully that should help it. You might need to specify the output bounds and resolution ,because in that strict mode, it can struggle getting valid sample points to guess it ! |
Thank you.
|
as far as I know, that is too late. You need to set it before starting python |
Put it at the system level
Still getting the same warp output and the same PROJ error messages as above. |
please provide a gdalwarp command line to reproduce the issue |
I made an experiment by:
I thing the test was not successful because of I won't have a try with older proj because I do not know if the test makes sense. And with the knowledge that I have it would be faster for me to burn the nodata polygons into the result. |
Two questions:
|
@rouault & @jratike80 Thanks for your help. I also wrote an equivalent python script to the warp operation. They all appear to behave the same. Please see the attachment. |
BTW, here is the gdalwarp stdout:
and
|
I am looking at the black areas in the transformed results and for me they look uniformly black. Not like being the original pixels copied as-is. I suppose that those pixels have value -9999 (nodata). Isn't that the result that you wanted to achieve? |
They look uniformly black because they are much larger than the transformed area (30m, compared to 0.5m). But they are not nodata. |
We tried conducting a transformation with a single resolution grid using the database. This resulted in the same behavior we were seeing with the GTG where a region with a nodata value in the transformation grid passed through the original data value. This was surprising to us since we had experienced a different behavior in this ticket which was using a pipeline transformation. gdalwarp -t_srs EPSG:9990+NOAA:98 -wo apply_vertical_shift=yes -wo sample_grid=yes -wo sample_steps=all "C:\Data\vypertemp\orig\low_res_itrf_input.tif" "C:\Data\vypertemp\orig\low_res_itrf_output_NC02_931.tif" We then tried doing a pipeline transformation (as in the previous ticket) with GDAL Warp with both a single resolution and GTG and we were successful in honoring the nodata transformation we expected. gdalwarp -vshift -ct "+proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +inv +proj=vgridshift +grids=us_noaa_nos_MLLW-ITRF2020_2020.0_(nwldatum_4.7.0_20240621).tif +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1" "C:\Data\vypertemp\orig\low_res_itrf_input.tif" "C:\Data\vypertemp\orig\low_res_itrf_out_pipeline_nwld_931.tif" It seems the bug we thought we had (a difference between single res and GTG behavior) was actually a difference between the behavior with a pipeline vs the database. Should we close this ticket and bring this question up in the mailing list? |
I've a fix in OSGeo/PROJ#4382 that makes the following to correctly work on areas where there is nodata in the grid with
why does it work correctly without PROJ_ONLY_BEST_DEFAULT=YES when you specify an explicit pipeline? The reason is that in that situation PROJ has no choice of pipelines, so it doesn't try to fallback to the dummy / ballpark transformation. The fix OSGeo/PROJ#4382 makes PROJ_ONLY_BEST_DEFAULT=YES to work properly in that context since GDAL uses proj_clone() and that function didn't propagate properly the flag set initially by PROJ_ONLY_BEST_DEFAULT=YES on the source object to the copy, thus causing the fallback ballpark transformation to still be used |
Yay! Thank you. I was just preparing some images to go with Glen's last comment and you made a fix before I could post the images -- awesome. |
So, if you want to have a control on what happens, use pipeline and don't trust on defaults, especially if it is hard to find out what the defaults are. (I don't mean that I like pipelines, usually if I write one it does not work). |
Thank you Even and Jukka! We really appreciate your help despite that we didn't post this to the right place or even ask the right question. It looks like the update is tagged for PROJ 9.6 (March). Until then we will fall back to pipelines. |
that's fine. It was far from obvious which part of the software stack was at fault. That said things are midly satisfactory with PROJ_ONLY_BEST_DEFAULT=YES causing a CPLError() to be emitted for each point failing to transform, which is both wanted, and unwanted... |
What is the bug?
We are using GDAL Warp and custom GTG grids to apply vertical transformations on raster files. The elevation values are transformed as expected except over the regions where the underlying transformation grid has NoDataValues, in which case the transformed values remain identical to the input. Ideally, the transformed values should be NoDataValue when the underlying transformation grid is NoDataValue. Is it be possible to get this behavior?
Thanks.
Steps to reproduce the issue
The input and output (transformed) raster files, our custom GTG grid, and the updated proj.db can be found here:
https://www.dropbox.com/scl/fo/3hg6szwq3gjywvj05daun/AHDL2ooWDQqCFOF6QU_7SiI?rlkey=vd3qexqtiw4gpm3e1eixfbpeq&st=vwmx3mfp&dl=0
We use the following warp options (in python) to apply the vertical shifts:
And this is the essence of the function that applies the transformation:
Versions and provenance
Additional context
No response
The text was updated successfully, but these errors were encountered: