Description
to_geotiff writes PAM .aux.xml sidecars next to the output file: a categorical RAT when the DataArray carries attrs['category_names'] (#3483), and STATISTICS_* entries for color_ramp= (#3537). When a later write targets the same path but produces no sidecar of its own, the old .aux.xml stays on disk and now describes the wrong pixels:
open_geotiff merges the sidecar back onto attrs, so a continuous raster written over an old categorical one comes back with category_names / category_colors from the overwritten file. QGIS then renders the float raster as three classes, and a rasterize -> to_geotiff round-trip re-writes the bogus RAT.
- GDAL tools and QGIS read the stale
STATISTICS_MINIMUM / STATISTICS_MAXIMUM and stretch the new data with the old file's range.
import numpy as np, xarray as xr
from xrspatial.geotiff import open_geotiff, to_geotiff
ys = 1000.0 - np.arange(8) * 10.0 - 5.0
xs = 2000.0 + np.arange(8) * 10.0 + 5.0
cat = xr.DataArray(np.arange(64, dtype='uint8').reshape(8, 8) % 3,
dims=('y', 'x'), coords={'y': ys, 'x': xs},
attrs={'crs': 32611,
'category_names': ['water', 'forest', 'urban']})
to_geotiff(cat, 'a.tif') # writes a.tif.aux.xml (RAT)
plain = xr.DataArray(np.arange(64, dtype='float32').reshape(8, 8),
dims=('y', 'x'), coords={'y': ys, 'x': xs},
attrs={'crs': 32611})
to_geotiff(plain, 'a.tif') # overwrite, no categories
open_geotiff('a.tif').attrs['category_names']
# ['water', 'forest', 'urban'] <- stale, from the overwritten file
GDAL's GTiff driver deletes associated PAM sidecars when it creates a dataset over an existing path (GDALDriver::QuietDelete), so gdal_translate onto the same path does not hit this.
Expected behavior
Writing a GeoTIFF to a string path should refresh the PAM sidecar: replaced when the new write emits one, removed when it does not. The .qml style sidecar is different. QGIS treats .qml as user styling that persists across data updates, so it should only be replaced by a new color_ramp= write.
Description
to_geotiffwrites PAM.aux.xmlsidecars next to the output file: a categorical RAT when the DataArray carriesattrs['category_names'](#3483), andSTATISTICS_*entries forcolor_ramp=(#3537). When a later write targets the same path but produces no sidecar of its own, the old.aux.xmlstays on disk and now describes the wrong pixels:open_geotiffmerges the sidecar back onto attrs, so a continuous raster written over an old categorical one comes back withcategory_names/category_colorsfrom the overwritten file. QGIS then renders the float raster as three classes, and a rasterize -> to_geotiff round-trip re-writes the bogus RAT.STATISTICS_MINIMUM/STATISTICS_MAXIMUMand stretch the new data with the old file's range.GDAL's GTiff driver deletes associated PAM sidecars when it creates a dataset over an existing path (
GDALDriver::QuietDelete), sogdal_translateonto the same path does not hit this.Expected behavior
Writing a GeoTIFF to a string path should refresh the PAM sidecar: replaced when the new write emits one, removed when it does not. The
.qmlstyle sidecar is different. QGIS treats.qmlas user styling that persists across data updates, so it should only be replaced by a newcolor_ramp=write.