Bug description
Calling glcm_texture() with multiple metrics in a different order than the internal VALID_METRICS tuple causes the output to get the wrong coordinate labels. Requesting ['entropy', 'contrast'] returns an array where result.sel(metric='entropy') actually contains contrast values, and the other way around.
Root cause
The numba kernel (_glcm_numba_kernel) always writes output slots in VALID_METRICS order. It walks the boolean metric_flags array from index 0 (contrast) through index 5 (entropy), incrementing a slot counter for each active flag. The backend functions (_glcm_numpy, _glcm_dask_numpy, etc.) then label the output with the user's metrics list, which can be in any order.
When the user requests ['entropy', 'contrast']:
metric_flags = [True, False, False, False, False, True] (contrast and entropy both active)
- The kernel writes contrast to
out[0] and entropy to out[1]
- The coordinate label array is
['entropy', 'contrast']
result.sel(metric='entropy') fetches out[0], which is actually contrast
Reproduction
import numpy as np
import xarray as xr
from xrspatial.glcm import glcm_texture
rng = np.random.default_rng(99)
data = rng.random((8, 8))
agg = xr.DataArray(data, dims=['y', 'x'])
contrast_solo = glcm_texture(agg, metric='contrast', window_size=3, levels=16, angle=0)
multi_rev = glcm_texture(agg, metric=['homogeneity', 'contrast'], window_size=3, levels=16, angle=0)
# These should match but don't:
print(contrast_solo.values[3, 3]) # 24.778
print(multi_rev.sel(metric='contrast').values[3, 3]) # 0.232 (this is actually homogeneity)
Impact
Any call with multiple metrics in non-standard order silently returns mislabeled data. The standard order (['contrast', 'dissimilarity', 'homogeneity', 'energy', 'correlation', 'entropy']) works by coincidence. Single-metric requests are also fine since there's only one slot.
Fix
Either sort the coordinate labels to match VALID_METRICS order, or reorder the kernel output to match the user's requested order.
Bug description
Calling
glcm_texture()with multiple metrics in a different order than the internalVALID_METRICStuple causes the output to get the wrong coordinate labels. Requesting['entropy', 'contrast']returns an array whereresult.sel(metric='entropy')actually contains contrast values, and the other way around.Root cause
The numba kernel (
_glcm_numba_kernel) always writes output slots inVALID_METRICSorder. It walks the booleanmetric_flagsarray from index 0 (contrast) through index 5 (entropy), incrementing a slot counter for each active flag. The backend functions (_glcm_numpy,_glcm_dask_numpy, etc.) then label the output with the user'smetricslist, which can be in any order.When the user requests
['entropy', 'contrast']:metric_flags=[True, False, False, False, False, True](contrast and entropy both active)out[0]and entropy toout[1]['entropy', 'contrast']result.sel(metric='entropy')fetchesout[0], which is actually contrastReproduction
Impact
Any call with multiple metrics in non-standard order silently returns mislabeled data. The standard order (
['contrast', 'dissimilarity', 'homogeneity', 'energy', 'correlation', 'entropy']) works by coincidence. Single-metric requests are also fine since there's only one slot.Fix
Either sort the coordinate labels to match
VALID_METRICSorder, or reorder the kernel output to match the user's requested order.