1

I have been trying to create a geoprocessing tool to delineate watershed basins for each point in a shapefile (parameter 1; CROSSING). The code below returns three 'basins', but they are all identical to each other. How can I alter this code to return a unique 'basin' for each point in 'CROSSING'?

import arcpy
from arcpy import env
from arcpy.sa import *
arcpy.env.addOutputsToMap = True
#DEFINE PARAMETERS & zLimit
DEM         = arcpy.GetParameterAsText(0) #digital elevation model
CROSSING    = arcpy.GetParameterAsText(1) #shp containing the stream crossings
PARCEL      = arcpy.GetParameterAsText(2) #polygon for clipping raster layer
EXTENT      = arcpy.GetParameterAsText(3) #search radius for SnapPourPoint()
LOCATION    = arcpy.GetParameterAsText(4) #output file path
zLimit      = 3.2808                      #for converting meters to feet
#CHECK OUT REQUIRED EXTENSION
arcpy.CheckOutExtension("Spatial")
#CLIPPING RASTER LAYER TO SMALLER AREA AROUND THE PARCEL
AOI = arcpy.Buffer_analysis(PARCEL,'AOI',10000)
USR = ExtractByMask(DEM,AOI)
arcpy.AddMessage('Raster optimization completed')
#GENERATING REQUIRED RASTER LAYERS
outFill = Fill(USR,zLimit)
outFlowDir = FlowDirection(outFill)
outFlowAcc = FlowAccumulation(outFlowDir)
#SETUP FOR LOOP
crossings = arcpy.SearchCursor(CROSSING)
i = 1
for OBJECTID in crossings:
    outSnapPoint = SnapPourPoint(CROSSING, outFlowAcc, EXTENT)
    arcpy.AddMessage('Flow direction analysis completed')
    watersheds = Watershed(outFlowDir,outSnapPoint,"VALUE")
    arcpy.RasterToPolygon_conversion(watersheds,LOCATION+"/BASIN_"+str(i)+'.shp')
    arcpy.AddMessage('Basin '+str(i)+' completed')
    arcpy.Delete_management(outSnapPoint)
    arcpy.Delete_management(watersheds)
    i = i + 1
arcpy.AddMessage('Watershed basins have been drawn, and are located in '+LOCATION)   
#DELETE EXCESS SHAPEFILES
EXCESS = [outFill,outFlowDir,outFlowAcc,outSnapPoint,watersheds,AOI,USR]
arcpy.Delete_management(EXCESS)
2
  • 2
    Do not use arcpy.SearchCursor in new code. Only use DA cursors. They are fast and Pythonic.
    – Vince
    Commented Aug 23, 2022 at 22:16
  • PEP8 asserts a standard for naming variables, and ALLUPPERCASE doesn't play a starring role. If you start out writing clean, portable code, you won't have break any bad habits later
    – Vince
    Commented Aug 23, 2022 at 22:30

2 Answers 2

0

Following some observations...

with arcpy.da.SearchCursor(CROSSING, ["OID@"]) as cursor:
  for row in cursor:
    where_clause = "OBJECTID = '{}'".format(row[0])
    layer_Select=arcpy.SelectLayerByAttribute_management(CROSSING, 'NEW_SELECTION', where_clause)
    outSnapPoint = SnapPourPoint(layer_Select, outFlowAcc, EXTENT)
    arcpy.AddMessage('Flow direction analysis completed')
    watersheds = Watershed(outFlowDir,outSnapPoint,"VALUE")
    arcpy.RasterToPolygon_conversion(watersheds,LOCATION+"/BASIN_"+str(i)+'.shp')
    arcpy.AddMessage('Basin '+str(i)+' completed')
    arcpy.Delete_management(outSnapPoint)
    arcpy.Delete_management(watersheds)
    i = i + 1

And if it doesn't work, you might need to export the selected feature to another shapefile before using it...

0

You need to add some fields in your SearchCursor. Your code should look like this:

with arcpy.da.SearchCursor(CROSSING, ["OID@"]) as cursor:
  for row in cursor:
    outSnapPoint = SnapPourPoint(CROSSING, outFlowAcc, EXTENT)
    arcpy.AddMessage('Flow direction analysis completed')
    watersheds = Watershed(outFlowDir,outSnapPoint,"VALUE")
    arcpy.RasterToPolygon_conversion(watersheds,LOCATION+"/BASIN_"+str(i)+'.shp')
    arcpy.AddMessage('Basin '+str(i)+' completed')
    arcpy.Delete_management(outSnapPoint)
    arcpy.Delete_management(watersheds)
    i = i + 1
4
  • 1
    Whilst I believe you are correct in improving the cursor, does this code work? Because the input into SnapPourPoint, never changes? You keep feeding the same layer to it. Either extract out each point or apply a selection to get each unique point.
    – Hornbydd
    Commented Aug 23, 2022 at 22:19
  • 1
    i is never initialized. Use for i,row in enumerate(cursor,start=1) instead. Plus string math is obtuse (use str.format instead).
    – Vince
    Commented Aug 23, 2022 at 22:20
  • i is instanciated at line 24 in his code... I just corrected the part of the code where the issue was (from my point of view). But I agree with you, the enumerate function is much better. Commented Aug 23, 2022 at 22:25
  • I just realised that you are correct, the SnapPourPoint must be a feature. He will need to export each point before using this function. Commented Aug 23, 2022 at 22:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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