[GRASS-user] Strange r.mapcalc results

Hi,

I am trying to find out if 2 raster layers are exactly identical. I am not an experienced mapcalc user, so I am wondering, where the 3200204 NULL values come from, in Test1. The result in Test2 is what I expected.

My obviously wrong understanding was that I wouldn't need the special operator ||| in Test1, as NULL values are already treated specially by isnull()

Any hint from the experts?

Hermann

Test1

$ r.mapcalc 'result = isnull(mapA) && isnull(mapT) || mapA == mapT ? 1 : 2'

$ r.stats -c result
1 799796
* 3200204

Test2

$ r.mapcalc 'result = isnull(mapA) && isnull(mapT) ||| mapA == mapT ? 1 : 2'

$ r.stats -c result
1 4000000

Test3

$ r.mapcalc 'result = isnull(mapA) && isnull(mapT) ? 1 : mapA == mapT ? 2 : 3'

$ r.stats -c result
1 3200204
2 799796

Hermann wrote:

I am trying to find out if 2 raster layers are exactly
identical.

I usually do

g.region rast=map1,map2

r.univar map1
r.univar map2

and make sure the output is the same.

another way is
r.mapcalc "diffmap = map1 - map2"
r.univar diffmap

see also wish #618
https://trac.osgeo.org/grass/ticket/618

Hamish

> r.univar based comparison:

What if there was a small geometric shift between the 2 maps. Would I notice if both maps have enough NULLs around the edges?

> r.mapcalc "diffmap = map1 - map2"

How would I separate NULL,NULL cases from cases where one map has a value, but the other has NULL?

And after thinking twice about my earlier posted test results, I still do not understand the logic of the isnull() results:

isnull(mapA) && isnull(mapT) gives NULL (Test1)
isnull(mapA) && isnull(mapT) gives 1 (Test3)

This doesn't make sense to me, which might be my fault, though.

Test1

$ r.mapcalc 'result = isnull(mapA) && isnull(mapT) || mapA == mapT ? 1 : 2'

$ r.stats -c result
1 799796
* 3200204

Test3

$ r.mapcalc 'result = isnull(mapA) && isnull(mapT) ? 1 : mapA == mapT ? 2 : 3'

$ r.stats -c result
1 3200204
2 799796

Hermann

Hamish wrote:

Hermann wrote:

I am trying to find out if 2 raster layers are exactly
identical.

I usually do

g.region rast=map1,map2

r.univar map1
r.univar map2

and make sure the output is the same.

another way is
r.mapcalc "diffmap = map1 - map2"
r.univar diffmap

see also wish #618
https://trac.osgeo.org/grass/ticket/618

Hamish

      _______________________________________________
grass-user mailing list
grass-user@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/grass-user

Hermann Peifer wrote:

I am trying to find out if 2 raster layers are exactly identical. I am
not an experienced mapcalc user, so I am wondering, where the 3200204
NULL values come from, in Test1. The result in Test2 is what I expected.

My obviously wrong understanding was that I wouldn't need the special
operator ||| in Test1, as NULL values are already treated specially by
isnull()

Any hint from the experts?

Test1

$ r.mapcalc 'result = isnull(mapA) && isnull(mapT) || mapA == mapT ? 1 : 2'

Test2

$ r.mapcalc 'result = isnull(mapA) && isnull(mapT) ||| mapA == mapT ? 1 : 2'

If mapA and mapT are both null, then Test 1 reduces to:

  result = isnull(mapA) && isnull(mapT) || mapA == mapT
-> result = isnull(null) && isnull(null) || null == null
-> result = 1 && 1 || null
-> result = 1 || null
-> result = null

while Test2 reduces to:

  result = isnull(mapA) && isnull(mapT) ||| mapA == mapT
-> result = isnull(null) && isnull(null) ||| null == null
-> result = 1 && 1 ||| null
-> result = 1 ||| null
-> result = 1

The || and && operators always propagate nulls (i.e. they return null
if either operand is null), while ||| and &&& return a non-null result
where possible (i.e. ||| returns 1 if either operand is non-zero, &&&
returns 0 if either operand is zero).

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

Glynn,

Thanks indeed for the enlightening. I am new to the mapcalc business and my obviously wrong (AWK-based) thinking was that mapcalc would do a lazy evaluation of the conditions, i.e. "1 && 1 || something" would always be 1, whatever "something" was. Now I know better.

Thanks again, Hermann

Glynn Clements wrote:

Hermann Peifer wrote:

I am trying to find out if 2 raster layers are exactly identical. I am not an experienced mapcalc user, so I am wondering, where the 3200204 NULL values come from, in Test1. The result in Test2 is what I expected.

My obviously wrong understanding was that I wouldn't need the special operator ||| in Test1, as NULL values are already treated specially by isnull()

Any hint from the experts?

Test1

$ r.mapcalc 'result = isnull(mapA) && isnull(mapT) || mapA == mapT ? 1 : 2'

Test2

$ r.mapcalc 'result = isnull(mapA) && isnull(mapT) ||| mapA == mapT ? 1 : 2'

If mapA and mapT are both null, then Test 1 reduces to:

  result = isnull(mapA) && isnull(mapT) || mapA == mapT
-> result = isnull(null) && isnull(null) || null == null
-> result = 1 && 1 || null
-> result = 1 || null
-> result = null

while Test2 reduces to:

  result = isnull(mapA) && isnull(mapT) ||| mapA == mapT
-> result = isnull(null) && isnull(null) ||| null == null
-> result = 1 && 1 ||| null
-> result = 1 ||| null
-> result = 1

The || and && operators always propagate nulls (i.e. they return null
if either operand is null), while ||| and &&& return a non-null result
where possible (i.e. ||| returns 1 if either operand is non-zero, &&&
returns 0 if either operand is zero).

Hermann Peifer wrote:

Thanks indeed for the enlightening. I am new to the mapcalc business and
my obviously wrong (AWK-based) thinking was that mapcalc would do a lazy
evaluation of the conditions, i.e. "1 && 1 || something" would always
be 1, whatever "something" was. Now I know better.

r.mapcalc never does "short-circuit" evaluation. This is true for if()
and ?: as well as &&,||,&&&,|||.

&& and || propagate nulls, while &&& and ||| return non-null where
possible. All four operators are symmetric, so e.g. "null() ||| 1" and
"1 ||| null()" both evaluate to 1.

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

Glynn Clements wrote:

Hermann Peifer wrote:

Thanks indeed for the enlightening. I am new to the mapcalc business and my obviously wrong (AWK-based) thinking was that mapcalc would do a lazy evaluation of the conditions, i.e. "1 && 1 || something" would always be 1, whatever "something" was. Now I know better.

r.mapcalc never does "short-circuit" evaluation. This is true for if()
and ?: as well as &&,||,&&&,|||.

&& and || propagate nulls, while &&& and ||| return non-null where
possible. All four operators are symmetric, so e.g. "null() ||| 1" and
"1 ||| null()" both evaluate to 1.

Thanks once again.

It might be worth adding this hint into the r.mapcalc documentation at: http://grass.itc.it/grass64/manuals/html64_user/r.mapcalc.html

Hermann