[GRASS-dev] [GRASS GIS] #3415: Mark raster NULL values as None in PyGRASS

#3415: Mark raster NULL values as None in PyGRASS
-------------------------+-------------------------
Reporter: marisn | Owner: grass-dev@…
     Type: defect | Status: new
Priority: normal | Milestone: 7.4.0
Component: PyGRASS | Version: unspecified
Keywords: | CPU: Unspecified
Platform: Unspecified |
-------------------------+-------------------------
At the moment PyGRASS is providing raster NULL values as is (i.e. for CELL
type they are marked as -2147483648). There is no function to check if
value is NULL (in C it is done with Rast_is_c/f/d_null_value).

The best would be to replace raster NULL values with None when raster is
read and None with NULL representation when it is written back. Such
approach would greatly simplify use of rasters in PyGRASS (i.e. "if
myrast[row][col] is not None:")

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/3415&gt;
GRASS GIS <https://grass.osgeo.org>

#3415: Mark raster NULL values as None in PyGRASS
--------------------------+-------------------------
  Reporter: marisn | Owner: grass-dev@…
      Type: defect | Status: new
  Priority: normal | Milestone: 7.4.0
Component: PyGRASS | Version: unspecified
Resolution: | Keywords:
       CPU: Unspecified | Platform: Unspecified
--------------------------+-------------------------

Comment (by zarch):

Replying to [ticket:3415 marisn]:
> At the moment PyGRASS is providing raster NULL values as is (i.e. for
CELL type they are marked as -2147483648). There is no function to check
if value is NULL (in C it is done with Rast_is_c/f/d_null_value).
>
> The best would be to replace raster NULL values with None when raster is
read and None with NULL representation when it is written back. Such
approach would greatly simplify use of rasters in PyGRASS (i.e. "if
myrast[row][col] is not None:")

Well, but then for CELL raster instead to have an array of integer you
will have an array of objects, I did not perform any benchmark but it
seems not very intuitive as well.
Perhaps we can define a `CELL_NULL` variable, and then you can write code
as: `if myrast[row] != CELL_NULL:` or an equivalent function instead of
`numpy.isnan` get `pygrass.raster.isnull`.
What do you think?

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/3415#comment:1&gt;
GRASS GIS <https://grass.osgeo.org>

#3415: Mark raster NULL values as None in PyGRASS
--------------------------+-------------------------
  Reporter: marisn | Owner: grass-dev@…
      Type: defect | Status: new
  Priority: normal | Milestone: 7.4.0
Component: PyGRASS | Version: unspecified
Resolution: | Keywords:
       CPU: Unspecified | Platform: Unspecified
--------------------------+-------------------------

Comment (by marisn):

You have a good point. As long as loading/saving can cope with whatever is
the NULL representation, a constant variable for grass.pygrass.raster
would do. I.e. grass.pygrass.raster.NULL that gets set to representation
of NULL for particular map when the map gets opened/created. Thus it
wouldn't matter if map is CELL or FCELL. In code one could then use
`map[row][cell] != map.NULL` to check for not NULL and `map[row][col] =
map.NULL` to set to NULL.
If nobody comes up with objection why it is a bad idea, could you, please,
implement it?

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/3415#comment:2&gt;
GRASS GIS <https://grass.osgeo.org>

#3415: Mark raster NULL values as None in PyGRASS
--------------------------+-------------------------
  Reporter: marisn | Owner: grass-dev@…
      Type: defect | Status: new
  Priority: normal | Milestone: 7.4.0
Component: PyGRASS | Version: unspecified
Resolution: | Keywords:
       CPU: Unspecified | Platform: Unspecified
--------------------------+-------------------------

Comment (by glynn):

Replying to [comment:1 zarch]:

> Well, but then for CELL raster instead to have an array of integer you
will have an array of objects, I did not perform any benchmark but it
seems not very intuitive as well.

For FP data, NaN should be used for nulls. This avoids the need for
explicit null handling in most cases.

For integer data, consider either (or both of):
1. converting to a
[https://docs.scipy.org/doc/numpy/reference/maskedarray.html masked
array]. This isn't quite as transparent as NaN, but is typically easier
than using a separate mask array.
2. converting to double (np.float64), with NaN as null. But this isn't
suitable if the data is to be used with e.g. bitwise operations, or used
as indices.

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/3415#comment:3&gt;
GRASS GIS <https://grass.osgeo.org>