From 0ece38149e229c0a45b1f46dd9cfd11e64836ab1 Mon Sep 17 00:00:00 2001 From: "Alan D. Snow" Date: Thu, 18 Jul 2024 15:50:40 -0500 Subject: [PATCH] REF:reproject: Make NaN default float nodata & update integer defaults (#797) --- docs/history.rst | 1 + rioxarray/raster_array.py | 20 +++++++------ rioxarray/raster_writer.py | 6 +++- .../integration/test_integration_rioxarray.py | 29 +++++++++++++++++++ 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/docs/history.rst b/docs/history.rst index 1ae96b14..6c0ffec4 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -3,6 +3,7 @@ History Latest ------ +- REF:reproject: Make NaN default float nodata & update integer defaults 0.16.0 ------ diff --git a/rioxarray/raster_array.py b/rioxarray/raster_array.py index bfbd6578..58de291a 100644 --- a/rioxarray/raster_array.py +++ b/rioxarray/raster_array.py @@ -47,21 +47,23 @@ # Based on: https://github.com/OSGeo/gdal/blob/ # dee861e7c91c2da7ef8ff849947713e4d9bd115c/ # swig/python/gdal-utils/osgeo_utils/gdal_calc.py#L61 +# And: https://github.com/rasterio/rasterio/blob/ +# 9e643c3f563a679aa5400d9b1a263df97b34f9e0/rasterio/dtypes.py#L99-L112 _NODATA_DTYPE_MAP = { 1: 255, # GDT_Byte 2: 65535, # GDT_UInt16 3: -32768, # GDT_Int16 - 4: 4294967293, # GDT_UInt32 - 5: -2147483647, # GDT_Int32 - 6: 3.402823466e38, # GDT_Float32 - 7: 1.7976931348623158e308, # GDT_Float64 + 4: 4294967295, # GDT_UInt32 + 5: -2147483648, # GDT_Int32 + 6: numpy.nan, # GDT_Float32 + 7: numpy.nan, # GDT_Float64 8: None, # GDT_CInt16 9: None, # GDT_CInt32 - 10: 3.402823466e38, # GDT_CFloat32 - 11: 1.7976931348623158e308, # GDT_CFloat64 - 12: None, # GDT_Int64 - 13: None, # GDT_UInt64 - 14: None, # GDT_Int8 + 10: numpy.nan, # GDT_CFloat32 + 11: numpy.nan, # GDT_CFloat64 + 12: 18446744073709551615, # GDT_UInt64 + 13: -9223372036854775808, # GDT_Int64 + 14: -128, # GDT_Int8 } diff --git a/rioxarray/raster_writer.py b/rioxarray/raster_writer.py index cc573ad9..137bb003 100644 --- a/rioxarray/raster_writer.py +++ b/rioxarray/raster_writer.py @@ -123,7 +123,11 @@ def _ensure_nodata_dtype(original_nodata, new_dtype): if numpy.issubdtype(new_dtype, numpy.complexfloating): nodata = original_nodata else: - original_nodata = float(original_nodata) + original_nodata = ( + float(original_nodata) + if not numpy.issubdtype(type(original_nodata), numpy.integer) + else original_nodata + ) failure_message = ( f"Unable to convert nodata value ({original_nodata}) to " f"new dtype ({new_dtype})." diff --git a/test/integration/test_integration_rioxarray.py b/test/integration/test_integration_rioxarray.py index 6843620c..991251ee 100644 --- a/test/integration/test_integration_rioxarray.py +++ b/test/integration/test_integration_rioxarray.py @@ -2165,6 +2165,35 @@ def test_reproject_transform_missing_shape(): assert reprojected.rio.transform() == affine +@pytest.mark.parametrize( + "dtype, expected_nodata", + [ + (numpy.uint8, 255), + (numpy.int8, -128), + (numpy.uint16, 65535), + (numpy.int16, -32768), + (numpy.uint32, 4294967295), + (numpy.int32, -2147483648), + (numpy.float32, numpy.nan), + (numpy.float64, numpy.nan), + (numpy.complex64, numpy.nan), + (numpy.complex128, numpy.nan), + (numpy.uint64, 18446744073709551615), + (numpy.int64, -9223372036854775808), + ], +) +def test_reproject_default_nodata(dtype, expected_nodata): + test_da = xarray.DataArray( + numpy.zeros((5, 5), dtype=dtype), + dims=("y", "x"), + coords={"y": numpy.arange(1, 6), "x": numpy.arange(2, 7)}, + ).rio.write_crs("epsg:3857", inplace=True) + if numpy.isnan(expected_nodata): + assert numpy.isnan(test_da.rio.reproject(4326).rio.nodata) + else: + assert test_da.rio.reproject(4326).rio.nodata == expected_nodata + + class CustomCRS: @property def wkt(self):