Raster calculator - The truth value of a raster is ambiguous

3535
3
Jump to solution
08-27-2018 11:22 AM
BrunoMoser
New Contributor II

Hi

I'm updating a landform classification script that ran under 10.3 to ArcGIS Pro 2.2. The model used a number of Single Output Map Algebra (SOMA) functions that I managed to replace with the raster calculators. That all seems to work, apart from this one formula:

ORIGINAL

medtpi1 == 1 and medtpi2 == 1 and rclsslope == 0

ArcGIS Pro

"%medtpi1%" == 1 and "%medtpi2%" == 1 and "%rclsslope%" == 0

I'm getting the error below and I must admit I'm not quite sure what to do with it. All other formulas have just two statements, so I thought the error might be related to the fact that there are three but this is a bit beyond my experience to date.

ERROR 000539: Traceback (most recent call last):
File "<expression>", line 1, in <module>
File "<string>", line 5, in rcexec
ValueError: The truth value of a raster is ambiguous. Invalid use of raster with Boolean operator or function. Check the use of parentheses where applicable.
Failed to execute (Raster Calculator (14))

Any help would be much appreciated.

Bruno

0 Kudos
1 Solution

Accepted Solutions
DanPatterson_Retired
MVP Emeritus

This error message means that you need to enclose your statements in round brackets because an equality check ( == ) normally returns the equivalent of True/False …

A demonstration of using simple arrays (aka rasters).

In short.... split up your conditions separately.  You really aren't going to save any time trying to get them in one big comparison, since you will most likely get one or more wrong OR not get the correct result

a  # array([0, 1, 2])
b  # array([3, 4, 5])
c  # array([2, 3, 4])

(a == 1)  # array([False,  True, False])
(b == 4)  # array([False,  True, False])
(c == 3)  # array([False,  True, False])

(a == 1) & (b == 4)  # array([False,  True, False])
(a == 1) & (b == 4) & (c == 3)  #  array([False,  True, False])

# ----  so the above work

# ---- failure 1... using `and` instead of `&`

(a == 1) and (b == 4) and (c == 3)

Traceback (most recent call last):...snip...
ValueError: The truth value of an array with more than one element is ambiguous.
Use a.any() or a.all()


# ---- failure 2... using `and` instead of `&` and dropping brackets

a == 1 and b == 4 and c == 3

Traceback (most recent call last):...snip...
ValueError: The truth value of an array with more than one element is ambiguous.
Use a.any() or a.all()


# ---- failure 3.... in desperation try partially correct

a == 1 & b == 4 & c == 3

Traceback (most recent call last):...snip...
ValueError: The truth value of an array with more than one element is ambiguous.
Use a.any() or a.all()



View solution in original post

3 Replies
DanPatterson_Retired
MVP Emeritus

This error message means that you need to enclose your statements in round brackets because an equality check ( == ) normally returns the equivalent of True/False …

A demonstration of using simple arrays (aka rasters).

In short.... split up your conditions separately.  You really aren't going to save any time trying to get them in one big comparison, since you will most likely get one or more wrong OR not get the correct result

a  # array([0, 1, 2])
b  # array([3, 4, 5])
c  # array([2, 3, 4])

(a == 1)  # array([False,  True, False])
(b == 4)  # array([False,  True, False])
(c == 3)  # array([False,  True, False])

(a == 1) & (b == 4)  # array([False,  True, False])
(a == 1) & (b == 4) & (c == 3)  #  array([False,  True, False])

# ----  so the above work

# ---- failure 1... using `and` instead of `&`

(a == 1) and (b == 4) and (c == 3)

Traceback (most recent call last):...snip...
ValueError: The truth value of an array with more than one element is ambiguous.
Use a.any() or a.all()


# ---- failure 2... using `and` instead of `&` and dropping brackets

a == 1 and b == 4 and c == 3

Traceback (most recent call last):...snip...
ValueError: The truth value of an array with more than one element is ambiguous.
Use a.any() or a.all()


# ---- failure 3.... in desperation try partially correct

a == 1 & b == 4 & c == 3

Traceback (most recent call last):...snip...
ValueError: The truth value of an array with more than one element is ambiguous.
Use a.any() or a.all()



curtvprice
MVP Esteemed Contributor

A few ArcGIS-specific comments to add to Dan's typically useful, yet pure Python discussion.

1) When you convert from SOMA to Raster Calculator 10x and arcpy map algebra you definitely need to use &, |, ~ instead of and, or, not. I have found the following help doc very useful:

Working with operators in Map Algebra—ArcGIS Help | ArcGIS Desktop 

2) Dan has a great point that you need to be very careful with complex expressions.

For example, this works in Raster Calculator. It processes left to right (maybe not what you want):

"ras1" & "ras2" & "ras3" == 1

This expression fails with the truth value is ambiguous error:

"ras1" & "ras2" == 1 & "ras3" == 1

Adding parentheses works, and probably is more likely to do what you want.

Extra parentheses are never a bad idea.

"ras1" & ("ras2" == 1) & ("ras3" == 1)

This help article also has some really great advice in it, including pointers on how to include regular (ie non-Spatial Analyst) tools inside map algebra expressions I hadn't noticed before. Worth a read!

Building complex statements—ArcGIS Help | ArcGIS Desktop 

DanPatterson_Retired
MVP Emeritus

Boolean and conditional logical operators have been around in every language that I have ever used.

More importantly, their roots predate computing appearing in such diverse fields as philosophy and psychology and even English and language studies.  Before we presuppose that these concepts are unique go GIS or even esri does require a rethink.  GIS problem solving has been done before… the tools to solutions just need to be applied from what they already know

Logical connective - Wikipedia 

List of logic symbols - Wikipedia  

So generically and language agnostic...

Aconditional statement results in a boolean, comparing multiple condition requires brackets if you want to use an conditional comparison between them

It is always preferable to put conditional or boolean checks in brackets to ensure the order of precedence is observed

0 Kudos