0

I have a script that adds output rasters' paths to a list and that list is used to loop through each input in a later module. I am getting the following error:

TypeError: expected raster or layer name

when I test if a path is in that list.

I have printed the list, the path is correct and has no spaces or other invalid characters (C:\Users\VanHorn\Documents\ArcGIS\scratch\Watersh_D8FlowD2.tif). The type is also raster (.tif). The TIFF also has spatial reference so that is not the issue. The file looks good when brought into ArcMap.

Here are sections of my code... the error is thrown at this line:

"if pract == acpfGWwatershed:"

# --------------------------------------------------------------------------------------------------------------
# Create lists to hold path to watersheds

def createListOfWatersheds():

    # create list to hold acpf watersheds
    acpfWatershedList = []

    # create list to hold existing watersheds
    existWatershedList = []

    return(acpfWatershedList, existWatershedList)

# --------------------------------------------------------------------------------------------------------------
# grass waterway watersheds

def acpfGWwatersheds(GWacpf, flowDir, acpfWatershedList):

    if arcpy.Exists(GWacpf):

        arcpy.AddMessage("Generating ACPF grass waterway watersheds...")

        # convert grass waterway feature to raster
        gwRas = arcpy.FeatureToRaster_conversion(GWacpf, "OBJECTID", "in_memory" + r"\gwRas", cellsize)

        # create list of grass waterway IDs
        gwIDs = [row[0] for row in arcpy.da.SearchCursor(GWacpf, "OBJECTID")]

        # generate bank cells of waterways- use later to get watersheds
        bankCells = Con(IsNull(gwRas), Expand(gwRas, 1, gwIDs), "", "")

        # buffer grasswaterways for mask
        buffDist = cellsize * 3
        gwBuffer = arcpy.Buffer_analysis(GWacpf, "in_memory" + r"\gwBuff", buffDist, "FULL", "FLAT", "NONE", "", "PLANAR")

        # mask banks to remove "headwaters"
        banks = ExtractByMask(bankCells, gwBuffer)

        # watershed
        acpfGWwatershed = Watershed(flowDir, banks, "Value")
        acpfGWwatershed.save()

        acpfWatershedList.append(acpfGWwatershed)

        del(gwRas, gwIDs, bankCells, buffDist, gwBuffer, banks)

        return(acpfWatershedList, acpfGWwatershed)

# --------------------------------------------------------------------------------------------------------------
# Runoff area treated table for suggested practices

def acpfRunoffWatersheds(catchments, acpfWatershedList, acpfTable):

    arcpy.AddMessage("Creating area treated table for ACPF practices...")
    arcpy.AddMessage(acpfWatershedList)

    # convert boundary to raster to use in Cell Statistics later
    boundaryRas = arcpy.FeatureToRaster_conversion(catchments, "riparianid", "in_memory" + r"\boundaryRas", cellsize)
    boundaryCon = Con(boundaryRas, "1000", "", "Value > 0")

    ACPFwatersheds = []

    ACPFwatersheds.append(boundaryCon)

    for pract in acpfWatershedList:
        if pract == acpfGWwatershed:
            GWcon = Con(pract, "1", "", "Value > 0")
            ACPFwatersheds.append(GWcon)

    acpfRunoffStack = CellStatistics(ACPFwatersheds, "SUM")

Complete code:

import arcpy
from arcpy import env
from arcpy.sa import *
import sys, string, os, time
arcpy.CheckOutExtension("Spatial")

arcpy.env.scratchWorkspace = env.scratchFolder

# --------------------------------------------------------------------------------------------------------------
# Create lists to hold path to watersheds

def createListOfWatersheds():

    # create list to hold acpf watersheds
    acpfWatershedList = []

    # create list to hold existing watersheds
    existWatershedList = []

    return(acpfWatershedList, existWatershedList)

# --------------------------------------------------------------------------------------------------------------
# grass waterway watersheds

def acpfGWwatersheds(GWacpf, flowDir, acpfWatershedList):

    if arcpy.Exists(GWacpf):

        arcpy.AddMessage("Generating ACPF grass waterway watersheds...")

        # convert grass waterway feature to raster
        gwRas = arcpy.FeatureToRaster_conversion(GWacpf, "OBJECTID", "in_memory" + r"\gwRas", cellsize)

        # create list of grass waterway IDs
        gwIDs = [row[0] for row in arcpy.da.SearchCursor(GWacpf, "OBJECTID")]

        # generate bank cells of waterways- use later to get watersheds
        bankCells = Con(IsNull(gwRas), Expand(gwRas, 1, gwIDs), "", "")

        # buffer grasswaterways for mask
        buffDist = cellsize * 3
        gwBuffer = arcpy.Buffer_analysis(GWacpf, "in_memory" + r"\gwBuff", buffDist, "FULL", "FLAT", "NONE", "", "PLANAR")

        # mask banks to remove "headwaters"
        banks = ExtractByMask(bankCells, gwBuffer)

        # watershed
        acpfGWwatershed = Watershed(flowDir, banks, "Value")

        desc = arcpy.Describe(acpfGWwatershed)
        arcpy.AddMessage(desc.dataType)
        arcpy.AddMessage(acpfGWwatershed)

        acpfWatershedList.append(acpfGWwatershed)

        del(gwRas, gwIDs, bankCells, buffDist, gwBuffer, banks)

        return(acpfWatershedList)

# --------------------------------------------------------------------------------------------------------------
# contour buffer strip watersheds

def acpfCBSwatersheds(CBSacpf, flowDir, acpfWatershedList):

    if arcpy.Exists(CBSacpf):

        arcpy.AddMessage("Generating ACPF CBS watersheds...")

        # convert CBS to raster
        CBSras = arcpy.FeatureToRaster_conversion(CBSacpf, "OBJECTID", "in_memory" + r"\CBSras", cellsize)

        # watershed
        acpfCBSwatershed = Watershed(flowDir, CBSras, "Value")

        acpfWatershedList.append(acpfCBSwatershed)

        del(CBSras)

        return(acpfWatershedList)

# --------------------------------------------------------------------------------------------------------------
# WASCOB watersheds

def acpfWASCOBwatersheds(WASCOBacpf, flowDir, acpfWatershedList):

    if arcpy.Exists(WASCOBacpf):

        arcpy.AddMessage("Generating ACPF WASCOB watersheds...")

        # convert WASCOB to raster
        WASCOBras = arcpy.FeatureToRaster_conversion(WASCOBacpf, "OBJECTID", "in_memory" + r"\WASCOBras", cellsize)

        # watershed
        acpfWASCOBwatershed = Watershed(flowDir, WASCOBras, "Value")

        acpfWatershedList.append(acpfWASCOBwatershed)

        del(WASCOBras)

        return(acpfWatershedList)

# --------------------------------------------------------------------------------------------------------------
# Runoff area treated table for suggested practices

def acpfRunoffWatersheds(catchments, acpfWatershedList, acpfTable):

    arcpy.AddMessage("Creating area treated table for ACPF practices...")

    # convert boundary to raster to use in Cell Statistics later
    boundaryRas = arcpy.FeatureToRaster_conversion(catchments, "riparianid", "in_memory" + r"\boundaryRas", cellsize)
    boundaryCon = Con(boundaryRas, "1000", "", "Value > 0")

    ACPFwatersheds = []

    ACPFwatersheds.append(boundaryCon)

    arcpy.AddMessage(type(acpfGWwatershed))
    arcpy.AddMessage(acpfGWwatershed)

    for pract in acpfWatershedList:
        desc2 = arcpy.Describe(pract)
        arcpy.AddMessage(desc2.dataType)
        arcpy.AddMessage(pract)
        if pract == acpfGWwatershed:
            GWcon = Con(pract, "1", "", "Value > 0")
            ACPFwatersheds.append(GWcon)
        elif pract == acpfCBSwatershed:
            CBScon = Con(pract, "10", "", "Value > 0")
            ACPFwatersheds.append(CBScon)
        elif pract == acpfWASCOBwatershed:
            WASCOBcon = Con(pract, "10", "", "Value > 0")
            ACPFwatersheds.append(WASCOBcon)


    acpfRunoffStack = CellStatistics(ACPFwatersheds, "SUM")
    acpfRunoffReclass = Reclassify(acpfRunoffStack, "Value", RemapValue([[1, "1"], [1001, "1"], [10, "2"], [1010, "2"], [100, "3"], [1100, "3"],
                                                                         [11, "12"], [1011, "12"], [101, "13"], [1101, "13"], [110, "23"], [1110, "23"],
                                                                         [111, "123"], [1111, "123"], [1000, "0"]]))

    # table with areas of stacked practices
    acpfRunoffTabulate = TabulateArea(catchments, "riparianid", acpfRunoffReclass, "Value", "in_memory" + r"\tabulateAreaACPF")
    arcpy.JoinField_management(acpfRunoffTabulate, "RIPARIANID", catchments, "riparianid", "acres")

    acpfRunoffDict = {"VALUE_0" : "pctNoTreat", "VALUE_1" : "pctGW", "VALUE_2" : "pctCBS", "VALUE_3" : "pctWASCOB", "VALUE_12" : "pctGW_CBS",
                      "VALUE_13" : "pctGW_WASCOB", "VALUE_23" : "pctCBS_WASCOB", "VALUE_123" : "pctGW_CBS_WASCOB"}

    # update table
    fieldList = [field.name for field in arcpy.ListFields(acpfRunoffTabulate)]

    keysList = acpfRunoffDict.keys()

    for field in fieldList:
        if field in keysList:

            dictvalue = acpfRunoffDict[field]
            arcpy.AddField_management(acpfRunoffTabulate, dictvalue, "DOUBLE")

            with arcpy.da.UpdateCursor(acpfRunoffTabulate, ["acres", dictvalue, field]) as cursor:
                for row in cursor:
                    row[1] = ((row[2]*0.00025)/row[0]) * 100
                    cursor.updateRow(row)

    # clean up, clean up
    keepList = ["RIPARIANID", "acres", "pctNoTreat", "pctGW", "pctCBS", "pctWASCOB", "pctGW_CBS", "pctGW_WASCOB", "pctCBS_WASCOB", "pctGW_CBS_WASCOB"]
    deleteList = []
    fList = arcpy.ListFields(acpfRunoffTabulate)
    for f in fList:
        if f.name not in keepList:
            if not f.required:
                deleteList.append(f.name)
    arcpy.DeleteField_management(acpfRunoffTabulate, deleteList)

    arcpy.CopyRows_management(acpfRunoffTabulate, acpfTable)

    del(boundaryRas, boundaryCon, pract, acpfRunoffStack, acpfRunoffReclass, acpfRunoffDict,
        fieldList, field, keysList, dictvalue, row, cursor, keepList, deleteList, fList, f, acpfRunoffTabulate)

## Inputs & Modules -----------------------------------------------------------------------------------------------

if __name__ == "__main__":

    catchments = arcpy.GetParameterAsText(0)
    flowDir = arcpy.GetParameterAsText(1)

    GWacpf = arcpy.GetParameterAsText(2)
    CBSacpf = arcpy.GetParameterAsText(3)
    WASCOBacpf = arcpy.GetParameterAsText(4)

    GWexist = arcpy.GetParameterAsText(5)
    CBSexist = arcpy.GetParameterAsText(6)
    Terrexist = arcpy.GetParameterAsText(7)
    Stripexist = arcpy.GetParameterAsText(8)
    WASCOBexist = arcpy.GetParameterAsText(9)

    acpfTable = arcpy.GetParameterAsText(10)
    existTable = arcpy.GetParameterAsText(11)

    if not(GWacpf or CBSacpf or WASCOBacpf or 
           GWexist or CBSexist or Terrexist or Stripexist or WASCOBexist):

        arcpy.AddError("no practices provided...Abort!!")
        sys.exit()

    arcpy.env.overwriteOutput = True
    arcpy.env.snapRaster = flowDir
    arcpy.env.extent = flowDir
    cellsize = float(arcpy.GetRasterProperties_management(flowDir, "CELLSIZEX").getOutput(0))

    acpfWatershedList, existWatershedList = createListOfWatersheds()

    acpfGWwatershed = acpfGWwatersheds(GWacpf, flowDir, acpfWatershedList)
    acpfCBSwatershed = acpfCBSwatersheds(CBSacpf, flowDir, acpfWatershedList)
    acpfWASCOBwatershed = acpfWASCOBwatersheds(WASCOBacpf, flowDir, acpfWatershedList)
    acpfRunoffWatersheds(catchments, acpfWatershedList, acpfTable)

Note that the empty list existWatershedList would be used in a second half of this code that is identical to the first half, just different parameters.

closed as off-topic by PolyGeo Jun 5 '18 at 21:23

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "When seeking help to debug/write/improve code always provide the desired behavior, a specific problem/error and the shortest code (as formatted text, not pictures) needed to reproduce it in the question body. Providing a clear problem statement and a code attempt helps others to help you." – PolyGeo
If this question can be reworded to fit the rules in the help center, please edit the question.

  • It is good that @smiller was able to volunteer time to help you here but whenever you are asking coding questions please try to develop and present a code snippet that illustrates what you have tried and where you are stuck rather than copy/pastes from or your whole code. – PolyGeo Jun 5 '18 at 21:21
1

The variable acpfGWwatershed is tested in the acpfRunoffWatersheds() function, but it's created in the acpfGWwatersheds() function. These aren't global variables. I don't see where you're calling these previous functions that should be returned, or passing it to the runoff function.

You'd be safest to modify this as calling acpfGWwatersheds() before your if statement in acpfRunoffWatersheds(). Probably as something similar to ws, wslist = acpfGWwatersheds(var1, var2, var3) and if pract == ws. Or you could pass in the watershed as a parameter in the runoff function.

EDIT: After full code was posted, determined that the line below was creating a list, when the desired output was a raster.

acpfGWwatershed = acpfGWwatersheds(GWacpf, flowDir, acpfWatershedList)

At least part of the issue stems from variable scope and overlapping naming between functions. An improvement would be to clean up the variable naming and (preferably) explicitly update lists rather than passing them into functions to be modified in place. Watch the return values of functions.

You also don't need to have a function to create these lists -- it makes the code more confusing and leads to the same scope issues.

Final suggestion -- when in doubt, take the code in sections (comment out what isn't needed) and print the type (not just value) of each variable to ensure you're getting the expected results.

  • Thank you. I will add the acpfGW module to the runoff module and see if that solves it. However, I have this at the bottom of the script below the if__name__ == "main": acpfGWwatershed = acpfGWwatersheds(GWacpf, flowDir, acpfWatershedList) Would this account for the issue you mention? – digiHUC Jun 5 '18 at 17:45
  • One fix you can do is to recognize that your acpfGWwatersheds function returns a tuple, not a single value. You could probably use acpfGWwatershed = acpfGWwatersheds(GWacpf, flowDir, acpfWatershedList)[0], or acpfGWwatershed, wslistvarname = acpfGWwatersheds(GWacpf, flowDir, acpfWatershedList). This would still depend on acpfGWwatershed as being recognized as a global variable -- you should pass it into the acpfRunoffWatersheds() function instead. I encourage you to use different variables outside of the function calls. – smiller Jun 5 '18 at 17:59
  • These suggestions have not been a fix...but I have found a work around where I do not have to test if the raster is in a list. I am not sure why I am getting this type error and would appreciate if someone has insight. I've used this same script structure but with feature classes and have no issue. I believe it must be something with how a raster is being defined, though after checking the type and getting 'Raster', and confirming that the raster datasets are valid I do not know what else to check. Thank you for your help, smiller! – digiHUC Jun 5 '18 at 18:58
  • Try printing the type of the value. I expect you're getting a tuple right now, not a string as you want / as your code expects. – smiller Jun 5 '18 at 19:01
  • Printing the type for the variable "pract" gives Raster Dataset – digiHUC Jun 5 '18 at 19:10
-1

@smiller sorted through my script, and the issue was that I was changing the type of acpfGWwatershed from a raster to a list when I returned a list in the second module.

Not the answer you're looking for? Browse other questions tagged or ask your own question.