[GRASS-dev] [gdal-dev] Setting NODATA to -nan

Hi,

(sorry to top post, just subscribed to the list)

A few notes w.r.t this thread:

- there's no universally "good" nodata value for GDAL. In the GDAL API, it is
a double value, but the way it is stored is highly dependant of formats. Might
be binary, or text (like in GeoTIFF with the GDAL_NODATA tag :
http://www.awaresystems.be/imaging/tiff/tifftags/gdal_nodata.html). In the case
of GeoTIFF, here's how it is serialized :

void GTiffDataset::WriteNoDataValue( TIFF *hTIFF, double dfNoData )

{
    char szVal[400];
    if (CPLIsNan(dfNoData))
        strcpy(szVal, "nan");
    else
        CPLsnprintf(szVal, sizeof(szVal), "%.18g", dfNoData);
    TIFFSetField( hTIFF, TIFFTAG_GDAL_NODATA, szVal );
}

The nan special case was done for cross OS compatibility, since there's no
standardized way among OS to serialize NaN. AFAIK, Linux must output "nan",
Windows "1#.QNAN" etc... Messy. On the reading side, same thing, "nan" is then
converted to the "most common" binary representation of a quiet NaN. GDAL code
that compare pixel values to nodata has a special case for nodata.

- the nodata value assigned to a GDAL band should theoretically be compatible
with the range of values compatible with the raster band datatype (e.g. in
[0,255] for byte), but this is not checked universally in the code
(gdal_translate -a_nodata checks it for example, drivers not as you can see in
the GeoTIFF case for example).

- for non-NaN floating point values, GDAL should normally compare the pixel
value with the nodata value with an epsilon test (due to potential
serialization as text).

- I've had a look at https://trac.osgeo.org/grass/changeset/65602 and my
understanding is that now a pixel value at NaN will be considered as null,
even if null_val is not NaN (but this is perhaps intended, if so, ignore
this).

- This is just for the sake of my curiosity: do you know how -nan pixel values
can be generated by GRASS in practice ? (This was what triggered all this: the
GDAL reporter was surprised to see pixels at -nan and nodata at nan, and
thought that something was wrong)

Anyway, too much time spent discussing about numbers that are not numbers :wink:
Let's move on.

Even

--
Spatialys - Geospatial professional services
http://www.spatialys.com

Even Rouault wrote:

- I've had a look at https://trac.osgeo.org/grass/changeset/65602 and my
understanding is that now a pixel value at NaN will be considered as null,
even if null_val is not NaN (but this is perhaps intended, if so, ignore
this).

- This is just for the sake of my curiosity: do you know how -nan pixel values
can be generated by GRASS in practice ? (This was what triggered all this: the
GDAL reporter was surprised to see pixels at -nan and nodata at nan, and
thought that something was wrong)

Rast_set_d_null_value() and Rast_set_f_null_value() use the all-ones
bit pattern. This is one of the many NaN values (anything with an
all-ones exponent and a non-zero mantissa is NaN). As the topmost bit
(i.e. the sign bit) is set, it's possible that some code would
consider that to be "-NaN". E.g. code which writes a leading "-" based
upon the sign bit before considering the other components would do so.

Rast_is_d_null_value() and Rast_is_f_null_value() treat any NaN as
null (specifically, they test whether the value is unequal to itself).

At one time, these functions (or rather, their predecessors) checked
explicitly for the all-ones pattern, but this was changed (in r33717
and r33752) to improve robustness. Apart from code explicitly setting
a value to "null", NaNs can arise from calculations (0.0/0.0, sqrt(x)
or log(x) for x<0, asin(x) or acos(x) for abs(x)>1, etc), and there's
no guarantee as to exactly which NaN representation will result.

--
Glynn Clements <glynn@gclements.plus.com>