Description
When glcm_texture is called with angle=None (the default, which averages all four GLCM angles), pixels with no valid co-occurrence pairs return 0.0 instead of NaN. This affects all-NaN inputs, single-cell rasters, and isolated valid pixels surrounded by NaN.
The single-angle path (angle=0/45/90/135) returns NaN in the same situation, so the two code paths disagree on what an undefined metric should be.
Reproduction
import numpy as np
import xarray as xr
from xrspatial.glcm import glcm_texture
data = np.full((6, 6), np.nan)
agg = xr.DataArray(data, dims=['y', 'x'])
# angle=None gives 0.0 for all metrics (wrong: should be NaN)
print(glcm_texture(agg, metric='contrast', window_size=3, levels=8).values)
# angle=0 gives NaN (correct)
print(glcm_texture(agg, metric='contrast', window_size=3, levels=8, angle=0).values)
Cause
In _run_glcm_on_quantized (xrspatial/glcm.py:326-337), each angle's per-pixel result is initialised to NaN. The kernel skips pixels with no valid pairs, leaving them NaN. The averaging code does tmp[nan_mask] = 0.0 and sums into the accumulator. When all four angles are NaN for a pixel, the result is 0.0/4.0 = 0.0 instead of NaN.
Expected behaviour
If at least one angle has valid pairs, the result should be the mean of the valid angles. If no angles have valid pairs, the result should be NaN.
Why it matters
A user cannot tell "metric is genuinely 0" apart from "no valid data". For texture analysis on rasters with NoData pixels (common in remote sensing), masked regions read as zero-texture rather than missing.
Description
When
glcm_textureis called withangle=None(the default, which averages all four GLCM angles), pixels with no valid co-occurrence pairs return 0.0 instead of NaN. This affects all-NaN inputs, single-cell rasters, and isolated valid pixels surrounded by NaN.The single-angle path (
angle=0/45/90/135) returns NaN in the same situation, so the two code paths disagree on what an undefined metric should be.Reproduction
Cause
In
_run_glcm_on_quantized(xrspatial/glcm.py:326-337), each angle's per-pixel result is initialised to NaN. The kernel skips pixels with no valid pairs, leaving them NaN. The averaging code doestmp[nan_mask] = 0.0and sums into the accumulator. When all four angles are NaN for a pixel, the result is0.0/4.0 = 0.0instead of NaN.Expected behaviour
If at least one angle has valid pairs, the result should be the mean of the valid angles. If no angles have valid pairs, the result should be NaN.
Why it matters
A user cannot tell "metric is genuinely 0" apart from "no valid data". For texture analysis on rasters with NoData pixels (common in remote sensing), masked regions read as zero-texture rather than missing.