[GRASS-user] r3.mapcalc / r.mapcalc: Logical Operators &&, || behave differently

Hi all,

for r3.mapcalc and r.mapcalc, there seems to be a difference regarding the logical operators (&& ||, etc.):

Assuming that two raster maps BAR and BAZ exist, the following statement creates new map content FOO whenever BAZ and BAR are not null:

r.mapcalc FOO='if((BAZ && BAR),42,null())'

Doing the same with volumes (BAZ3, BAR3) results in an error message:

r3.mapcalc FOO3='if((BAZ3 && BAR3),42,null())'

=>

Incorrect argument types to function or()
Parse error

Where's my mistake ?

FWIW: I'm using GRASS6.4.2 on Linux

GRASS 6.4.2 (2012)
Revision: 45934

Best,
Peter

<peter.loewe@gmx.de>

"Peter Löwe" wrote:

for r3.mapcalc and r.mapcalc, there seems to be a difference
regarding the logical operators (&& ||, etc.):

Assuming that two raster maps BAR and BAZ exist, the following
statement creates new map content FOO whenever BAZ and BAR are not
null:

r.mapcalc FOO='if((BAZ && BAR),42,null())'

Not quite.

The result will be 42 if both BAZ and BAR are non-null and non-zero.
If either are null or either are zero, the result will be null.

Regarding &&:

* A && B is null if either A or B are null, otherwise ...

* A && B is zero if either A or B are zero, otherwise ...

* A && B is one.

Regarding if():

* if(A,B,C) is null if A is null, otherwise ...

* if(A,B,C) is B if A is non-zero, otherwise ...

* if(A,B,C) is C

So if either BAZ or BAR are null, (BAZ && BAR) will be null and the
if() function will evaluate to null regardless of its second and third
arguments.

If neither are null, then (BAZ && BAR) will be 0 if either BAZ or BAR
are zero, and 1 if both are non-zero.

Doing the same with volumes (BAZ3, BAR3) results in an error message:

r3.mapcalc FOO3='if((BAZ3 && BAR3),42,null())'

FWIW, you should change the quoting to:

  r3.mapcalc 'FOO3 = if((BAZ3 && BAR3),42,null())'

This will work in both 6.x and 7.x, whereas your original version will
only work in 6.x (in 7.x, r.mapcalc/r3.mapcalc use the GRASS argument
parser, so the expression musn't match the "option=value" syntax;
adding spaces around the "=" avoids this issue).

=>

Incorrect argument types to function or()
Parse error

Where's my mistake ?

I suspect that either BAZ3 or BAR3 is a floating-point volume. The
arguments to logical operators must be integers.

Also, I don't see how you can get a reference to "or()" from an
expression involving only "&&".

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

Glynn,

thanks for your quick response:
You are of course correct regarding the non-null/non-zero aspects and I stand corrected for the substellar cut'n past blunder :slight_smile:

Yet still I'm puzzled, as I hoped that type casting to INT would do the trick:

r3.mapcalc l01i='int(l01)'
r3.mapcalc l02i='int(l02)'

GRASS 6.4.2 (utm10n_wgs84):~ > r3.mapcalc "FOO3 = if((l01i || l02i),42,null())"
Incorrect argument types to function or()
Parse error

same here:
GRASS 6.4.2 (utm10n_wgs84):~ > r3.mapcalc "FOO3 = if((l01i && l02i),42,null())"
Incorrect argument types to function and()
Parse error

FWIW, the volumes are quite trivial:
GRASS 6.4.2 (utm10n_wgs84):~ > r3.info l01i
+----------------------------------------------------------------------------+
| Layer: l01i Date: Wed Aug 20 22:32:46 2014 |
| Mapset: PERMANENT Login of Creator: ploewe |
| Location: utm10n_wgs84 |
| DataBase: /home/cegit/ploewe/geodata/locations |
| Title: ( l01i ) |
| Timestamp: none |
|----------------------------------------------------------------------------|
| |
| Type of Map: 3d cell Number of Categories: 0 |
| Data Type: double |
| Rows: 1400 |
| Columns: 979 |
| Depths: 188 |
| Total Cells: 257672800 |
| Projection: UTM (zone 10) |
| N: 5121985 S: 5107985 Res: 10 |
| E: 567605 W: 557815 Res: 10 |
| T: 2550 B: 670 Res: 10 |
| Range of data: min = 1 max = 1 |
| |
| Data Source: |
| |
| |
| |
| Data Description: |
| generated by r3.mapcalc |
| |
| Comments: |
| r3.mapcalc |
| |
+----------------------------------------------------------------------------+

Any further advice would be much appreciated.

Best,
Peter

<peter.loewe@gmx.de>

Gesendet: Mittwoch, 20. August 2014 um 22:14 Uhr
Von: "Glynn Clements" <glynn@gclements.plus.com>
An: "Peter Löwe" <peter.loewe@gmx.de>
Cc: grass-user@lists.osgeo.org
Betreff: Re: [GRASS-user] r3.mapcalc / r.mapcalc: Logical Operators &&, || behave differently

"Peter Löwe" wrote:

> for r3.mapcalc and r.mapcalc, there seems to be a difference
> regarding the logical operators (&& ||, etc.):
>
> Assuming that two raster maps BAR and BAZ exist, the following
> statement creates new map content FOO whenever BAZ and BAR are not
> null:
>
> r.mapcalc FOO='if((BAZ && BAR),42,null())'

Not quite.

The result will be 42 if both BAZ and BAR are non-null and non-zero.
If either are null or either are zero, the result will be null.

Regarding &&:

* A && B is null if either A or B are null, otherwise ...

* A && B is zero if either A or B are zero, otherwise ...

* A && B is one.

Regarding if():

* if(A,B,C) is null if A is null, otherwise ...

* if(A,B,C) is B if A is non-zero, otherwise ...

* if(A,B,C) is C

So if either BAZ or BAR are null, (BAZ && BAR) will be null and the
if() function will evaluate to null regardless of its second and third
arguments.

If neither are null, then (BAZ && BAR) will be 0 if either BAZ or BAR
are zero, and 1 if both are non-zero.

> Doing the same with volumes (BAZ3, BAR3) results in an error message:
>
> r3.mapcalc FOO3='if((BAZ3 && BAR3),42,null())'

FWIW, you should change the quoting to:

  r3.mapcalc 'FOO3 = if((BAZ3 && BAR3),42,null())'

This will work in both 6.x and 7.x, whereas your original version will
only work in 6.x (in 7.x, r.mapcalc/r3.mapcalc use the GRASS argument
parser, so the expression musn't match the "option=value" syntax;
adding spaces around the "=" avoids this issue).

> =>
>
> Incorrect argument types to function or()
> Parse error
>
> Where's my mistake ?

I suspect that either BAZ3 or BAR3 is a floating-point volume. The
arguments to logical operators must be integers.

Also, I don't see how you can get a reference to "or()" from an
expression involving only "&&".

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

"Peter Löwe" wrote:

Yet still I'm puzzled, as I hoped that type casting to INT would do the trick:

r3.mapcalc l01i='int(l01)'
r3.mapcalc l02i='int(l02)'

It appears that 3D volumes are always floating-point.

So you would need to use e.g.

  r3.mapcalc "FOO3 = if((int(l01) || int(l02)),42,null())"
or
  r3.mapcalc "FOO3 = if((l01 != 0 || l02 != 0),42,null())"

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