If you are stuck at "if" – Part 1

If-then-else logic is a simple yet powerful concept for performing different actions based on different conditions. If-then-else logic can be explained like this:

IF some condition is true, THEN
   perform an action;
ELSE the condition is false,
   perform a different action.

This is a three part blog which talks about different examples of if-then-else conditions and ways to implement it in ArcGIS.

Part 1 – Gives examples of quick and dirty ways of using the Calculate Value tool to create branches using if statements in a model.

Part 2 – Gives an example of creating and connecting an if-then-else script tool for branching in a model. The If Product license exists example of Calculate value
from part 1 has been converted into script tools to explain the concepts.

Part 3 –Gives three case examples of using script tools in a model. This part highlights the use of various capabilities of ModelBuilder such as:

  • using a branching script in a model
  • merging two branches
  • creating model parameters
  • using Value list filter in a model
  • setting preconditions
  • using an iterator in a model
  • creating a nested model or a model within a model

————————————————————————————————————————————————————————–

Examples of using the Calculate Value tool to create branches using if-else logic
In this blog part we cover five examples of using if-then-else logic code in the Calculate Value tool. There are various reasons to use either Calculate Value or a script tool for branching such as:

Reasons to use Calculate Value tool:

  • It is easy to use.
  • The code remains inside the model as compared to a script tool which reference an external Python file.
  • It has a built-in list of output data types.

Or there are reasons to use a Script tool:

  • It is easier to manage and debug large code examples using the Python IDE than in the Calculate Value tool.
  • If the code has many if and else conditions or too many possibilities of what input value could be. For example, if you are creating an “if” tool for any type of input dataset. There are more than 20 possible dataset types and it will make the code block in the Calculate Value tool too big to manage and debug.
  • The Calculate Value tool only has one output Boolean parameter (either true or false) so if you want to check for multiple conditions you have to add the Calculate Value tool multiple times with the logic to test against. For Example – Suppose you want to check if the input is a shapefile or a feature class from a geodatabase. The only way to do this is to add two Calculate Value tools and add the logic for checking just for the shapefile or just the feature class separately. In comparison the script tool can have two output Boolean parameters from a single tool and the tool redundancy can be avoided by adding the logic for both the checks in a single script tool.
  • If scripts are your style and comfort preference (Oh yes! I have heard this from many)

Where to start?
Just in case you are new to ModelBuilder you might want to start with the following topic and tutorials:

Now that you are comfortable with the ModelBuilder interface and vocabulary you can get started with this blog by downloading the models from here.

You can access the Calculate Value tool in ModelBuilder from the Insert > Model Only tools menu or right click side menu. Calculate Value tool returns a value based on a specified Python expression. Learn more about the tool by clicking here.

————————————————————————————————————————————————————————–

Example 1 – If Product License Exists
Tools have different license level requirements. Some tools run at ArcView level while others need an ArcInfo license. If you want to run tools based on product license levels in a model a quick way to check is by using if logic in Calculate Value tool.

The following example uses the Erase tool if the ArcInfo license is available and uses a combination of multiple tools to execute the same simple task as the Erase tool if the license is not available. You need to have some knowledge of the license level requirement for each tool. You can easily check this from the individual tool documentation.

The check is especially important, if you are sharing the models with your peers as the product level could be different from one user to another, and using this license level check can significantly minimizes the processing time, especially if it is a big model or large data.

For all examples the if-then-else code in Calculate Value tool is written in Python using ArcPy, a Python site package that encompasses and further enhances the arcgisscripting module. This example uses the ArcPy ProductInfo function to check the availability of the product license and sets the Boolean output parameter to true or false based on the if condition.

If Product License Exists Condition

Expression 

x("%ProductToCheck%")

Code Block

def x(ProductToCheck):
import arcpy
if arcpy.ProductInfo() == ProductToCheck:
    return "true"
else:
    return "false"
If Product License Does Not Exist Condition

Expression

x("%ProductToCheck%")

Code Block

def x(ProductToCheck):
import arcpy
if arcpy.ProductInfo() == ProductToCheck:
    return "false"
else:
    return "true"

————————————————————————————————————————————————————————–

Example 2 – If Extension Exists
Esri offers a wide range of optional extensions that can dramatically expand the capabilities of ArcGIS. Some of these ArcGIS tools are packaged in different extensions. The following example executes the Geographically Weighted Regression tool from Spatial Statistics toolbox. Geographically Weighted Regression requires an ArcInfo license or the Spatial Analyst extension or the Geostatistical Analyst extension. The example model checks to see if an ArcInfo license is available just as in the previous example and if the license is not available checks to see if either the Spatial or Geostats extension is available using the Calculate Value tool. The Boolean outputs (True and False) are passed to the Merge Branch, a tool often used in if-then-else logic. Merge Branch takes any number of inputs and these inputs can be of any data type (feature layer, Boolean, String, Double, and so on). When Merge Branch executes, it examines the list of inputs, and outputs the first valid value it finds. In the case of Booleans, it examines the list and outputs the True if any of the inputs are true. If none of the inputs are true, the output of Merge Branch is
false.

If neither the product license (ArcInfo) nor any of the two extensions are available the tool does not execute.

The example uses the CheckExtension acrpy function to check the availability of the extension and CheckOutExtension function to check out the extension for use.

If Extension Exists Condition

Expression

getExtension()

Code Block

def getExtension():
import arcpy
if arcpy.CheckExtension("Spatial") == "Available":
    arcpy.CheckOutExtension("Spatial")
        return "true"
elif arcpy.CheckExtension("Geostats") == "Available":
    arcpy.CheckOutExtension("Geostats")
        return "true"
else:
    return "false"

————————————————————————————————————————————————————————–

Example 3 – If Feature Class Exists
In this example the Calculate Value tool checks if a feature class exists in a workspace and if it exists, adds a field, adds a string value of “Existing “using the Calculate Field tool. If it does not exists the model copies the feature class from a backup location, adds a field, calculates that field with values of the date and time that it was copied and then the two feature classes are input to Merge Branch tool. Merge Branch examines which one has been updated with a valid value and outputs the feature class to merge with the other two feature classes.

The example uses the Exists arcpy function to check if the feature class exists.

If Feature Class Exists Condition

Expression

x("%FeatureClassToCheck%", "%Workspace%")

Code Block

def x(FeatureClassToCheck, Workspace):
import arcpy
arcpy.env.workspace = Workspace
if arcpy.Exists(FeatureClassToCheck):
    return "true"
else:
    return "false"
If Feature Class Does Not Exist Condition

Expression

x("%FeatureClassToCheck%", "%Workspace%")

Code Block

def x(FeatureClassToCheck, Workspace):
import arcpy
arcpy.env.workspace = Workspace
if arcpy.Exists(FeatureClassToCheck):
    return "false"
else:
    return "true"

————————————————————————————————————————————————————————–

Example 4 – If the input is Point, Polyline or Polygon Features Class
If you want to find whether the input feature class is a point, line or polygon you can use a simple if logic in the Calculate Value tool. For example if the input feature class is a polygon then the Feature To Point tool converts the input into a point features class and uses it for a network analysis. If the input is points, it uses the point feature class directly into the network analysis. You can check if the input is a Line or a Point in the similar way as shown in the example below.

The example uses the Describe function to describe the shape type of the data.

If Feature Type Exists Condition

Expression

x(r"%InputFeatureClass%")

Code Block

def x(InputFeatureClass):
import arcpy
desc = arcpy.Describe(InputFeatureClass)
type = desc.shapeType
if type == "Polygon":
    return "true"
else:
    return "false"

————————————————————————————————————————————————————————–

Example 5 – If Feature Type Exists
You can check whether the input to your model is a shapefile or a feature class from a geodatabase using the Calculate Value tool as shown in this example. It checks to see if the input is a shapefile then adds a field and calculates area before calculating population density for the block groups. If it is a feature class from a geodatabase the area field already exists and the model can directly proceed to calculate population density. You can extend the same logic to find whether the input is a layer file or a feature layer in the map’s table of content.

The example uses the Describe to describe the
data type of the data.

If input is a Shapefile Condition

Expression

x(r"%InputData%")

Code Block

def x(InputData):
import arcpy
desc = arcpy.Describe(InputData)
type = desc.datatype
if type == "ShapeFile":
    return "true"
else:
    return "false"
If input is a Feature Class Condition

Expression

x(r"%InputData%")

Code Block

def x(InputData):
import arcpy
desc = arcpy.Describe(InputData)
type = desc.datatype
if type == "FeatureClass":
    return "true"
else:
    return "false"
This entry was posted in Analysis & Geoprocessing and tagged , , , , , , . Bookmark the permalink.

Leave a Reply

6 Comments

  1. grahash says:

    I found this blog because I was looking for examples of using IF-THEN that might apply to my situation.

    I’ve set up a modified version of the “Clip And Ship” geoprocessing example on one of our sites. It works, but I would like to limit the maximum extent where the geoprocessing tool can be run. For example, if the user selects an area greater than 2000 sq. miles, I would like the model to display a message indicating the area is too large.

    Unfortunately, I have limited experience with Model Builder and no experience with Python. Is it possible to apply IF-THEN to a user selected polygon in Model Builder? If so, could you provide an example model?

  2. shitijmehta says:

    I created a model that shows you how to work with the issue you have with area > 2000 sq. miles. If you provide your email I would be more than happy to send the model and the script tool for adding a custom message to you.

  3. nuisanceheather says:

    Hi Shitijmehta,

    Could you please help me find out why and how to fix a Geoprocessing model (v10)? The current model calculates census data and needs to have an if-then-else using the Calculate Value tool. The code below is working wonderfully on desktop, but crashes in a service with the following error:

    Error 000539: Error running expression: x(r”c:arcgisserverarcgisjobsPopulation_toolsmodel3_gpserverjb18558850e7e47799ascratchscratch.gdbCensus_join”) : No module named collections
    Failed to execute

    Python code within Calculate Value in Geoprocessing Service:

    # First Calculate Value should count the number of rows in the feature class and continue with
    # the calculations if it is = 1 row.
    Expression:
    x(r”%Census_join%”)

    Code Block:
    def x(InputFeatureClass):
    import arcpy
    result = arcpy.GetCount_management(InputFeatureClass)
    if int(result.getOutput(0)) == 1:
    return “true”
    else:
    return “false”

    # Second Calculate Value should count the number of rows in the feature class and continue with
    # the calculations if there is > 1 row.
    Expression:
    x(r”%Census_join%”)

    Code Block:
    def x(InputFeatureClass):
    import arcpy
    result = arcpy.GetCount_management(InputFeatureClass)
    if int(result.getOutput(0)) == 1:
    return “false”
    else:
    return “true”

    Data type: Boolean

    Any help to make this work as a service…would be hugely helpful!
    Thank you.

  4. shitijmehta says:

    I don’t see a reason that it should fail with Calculate Value. Are you using any other code or script tool in your model? The error is an import error in Python. It is not able to find the Collections that you are importing. This error is not with the code block in calculate value tool but something else, may be a mis-configured Python on your system.

    Hope you can figure it out.

  5. curtvprice says:

    Re: “The code remains inside the model as compared to a script tool which reference an external Python file”

    It should be noted that with Arc 9.x and later, you can import a python script into the toolbox file so there are no extra files needed to be packaged with the tbx.

    Another very important reason to use script tools is over modelbuilder is the ability to create a validation class. This can save the user a lot of frustration by checking the input for potential issues before the tool runs.

    That said, I’m a big fan of 10.x modelbuilder for automating simple workflows, especially with the vastly improved iteration capability provided by the new 10.x iterators.

  6. shitijmehta says:

    Good point Curt on validation class. Thanks!