Describe the bug
build_vrt writes a <GeoTransform> element into the output VRT even when the source TIFF has no georeferencing. A plain (non-georeferenced) TIFF reads back with georef_status='none', but after wrapping it in a VRT with build_vrt, the VRT reads as georef_status='transform_only' with a fabricated identity transform (1, 0, 0, 0, -1, 0).
This is silent metadata fabrication. Downstream spatial functions can then treat pixel coordinates as real CRS-space coordinates, and nothing distinguishes the fabricated transform from a real one.
Root cause in xrspatial/geotiff/_vrt.py: the per-source metadata dict always stores geo.transform, even when geo.has_georef is false. With no georeferencing, geo.transform is the default identity GeoTransform(origin_x=0, origin_y=0, pixel_width=1, pixel_height=-1). The writer always emits a <GeoTransform> line, so that identity leaks into the VRT XML.
Reproduction
import numpy as np, xarray as xr, tempfile, os
from xrspatial.geotiff import to_geotiff, open_geotiff, build_vrt
d = tempfile.mkdtemp()
arr = xr.DataArray(np.arange(12, dtype='float32').reshape(3, 4))
tif = os.path.join(d, 'plain.tif')
to_geotiff(arr, tif)
print(open_geotiff(tif).attrs['georef_status']) # none
vrt = os.path.join(d, 'plain.vrt')
build_vrt(vrt, [tif])
out = open_geotiff(vrt)
print(out.attrs['georef_status']) # transform_only (BUG)
print(out.attrs['transform']) # (1.0, 0.0, 0.0, 0.0, -1.0, 0.0)
Expected behavior
When every source TIFF has no georeferencing (geo.has_georef is false), build_vrt should not emit a <GeoTransform> element. The resulting VRT then preserves georef_status='none'. A VRT without a <GeoTransform> already reads back as none with integer pixel coordinates, so the reader side needs no change.
Mixed sources (some georeferenced, some not) should be rejected with a clear error, matching the existing fail-loud gates in build_vrt. A non-georeferenced tile cannot be placed correctly on a georeferenced mosaic.
Additional context
Severity: high. The fabricated transform is indistinguishable from a real one to downstream consumers.
Describe the bug
build_vrtwrites a<GeoTransform>element into the output VRT even when the source TIFF has no georeferencing. A plain (non-georeferenced) TIFF reads back withgeoref_status='none', but after wrapping it in a VRT withbuild_vrt, the VRT reads asgeoref_status='transform_only'with a fabricated identity transform(1, 0, 0, 0, -1, 0).This is silent metadata fabrication. Downstream spatial functions can then treat pixel coordinates as real CRS-space coordinates, and nothing distinguishes the fabricated transform from a real one.
Root cause in
xrspatial/geotiff/_vrt.py: the per-source metadata dict always storesgeo.transform, even whengeo.has_georefis false. With no georeferencing,geo.transformis the default identityGeoTransform(origin_x=0, origin_y=0, pixel_width=1, pixel_height=-1). The writer always emits a<GeoTransform>line, so that identity leaks into the VRT XML.Reproduction
Expected behavior
When every source TIFF has no georeferencing (
geo.has_georefis false),build_vrtshould not emit a<GeoTransform>element. The resulting VRT then preservesgeoref_status='none'. A VRT without a<GeoTransform>already reads back asnonewith integer pixel coordinates, so the reader side needs no change.Mixed sources (some georeferenced, some not) should be rejected with a clear error, matching the existing fail-loud gates in
build_vrt. A non-georeferenced tile cannot be placed correctly on a georeferenced mosaic.Additional context
Severity: high. The fabricated transform is indistinguishable from a real one to downstream consumers.