I am working with a watershed map, and I was wondering if there is a function or a way that I can get ArcMap to number the watersheds. For instance, if we have watershed X numbered as 0, I want the watersheds that surround/or share a boundary with watershed X to be numbered 1, and the watersheds that surround/ or share a boundary with the number 1 watersheds to be numbered 2 and so on. Is there a way this can be done by building a model in ModelBuilder? I would like to save it so when I change a watershed layer and run the model it will do the same in a new watershed area.
-
Can you demonstrate with a picture what you're after?– blah238Commented Jul 11, 2012 at 20:34
-
3Out of interest, given you're dealing with watersheds, would a numbering system such as Strahler or Pfafstetter be more appropriate as it deals with upstream and downstream directionality?– om_hennersCommented Jul 12, 2012 at 1:12
-
Well I'm only looking at the watersheds as a whole not going into the streams. I believe if i would use that if I was doing the analysis at stream level.– user8759Commented Jul 12, 2012 at 13:42
2 Answers
I'm thinking you could do something with Select by Location, Calculate Field and iteration in ModelBuilder... see this page for an example: Iteration using a count or Boolean condition
-
I think this may work. I will try it out. However do you know if it will assign it values? I looked at the example but does each Interaction give those boxes a new value and if so does it give them all the same values?– user8759Commented Jul 11, 2012 at 20:49
-
This answer is not meant to be a complete solution, only a starting point. The Calculate Field tool is what I would use assign the selected features values. Some care would need to be taken to ensure that the previously selected features are not also calculated with each iteration though.– blah238Commented Jul 11, 2012 at 21:09
-
The SelectByLocation tool gives you an option for NEW_SELECTION so you're not overwriting your last iteration.– RoyCommented Jul 12, 2012 at 11:23
-
Thank you everyone who has answered I will be working on creating this and if I run into anything complicated I will ask for advice.– user8759Commented Jul 12, 2012 at 13:07
-
Hello, is there a way I can control the Select by Layer tool to interate, but when it interates for the second or third time to not include the previews times it interated?– user8759Commented Jul 18, 2012 at 18:29
A possible solution written in arcpy Python based on @blah238's solution above. If you wanted to stay in a model builder environment, you could just take the expression from the CalculateFieldManagement
line and use that in model builder. Just note the extra setting of -1 and 0 to the original field in case the input is a shapefile.
import arcpy
import sys
def watershed_counter(watershed_lyr, calc_attribute):
current_count = int(arcpy.GetCount_management(watershed_lyr).getOutput(0))
assert current_count == 1, "Too many features selected!"
watershed_value = 0
arcpy.AddMessage("Calculating base watershed")
#We calculate to -1 as if base file is shapefile it uses 0 instead of Null
#as placeholders for no data, and that'a where we want to start the
#watershed count
arcpy.CalculateField_management(watershed_lyr, calc_attribute, -1)
while watershed_value >= 0:
arcpy.AddMessage("Selecting new watersheds")
arcpy.SelectLayerByLocation_management(watershed_lyr, 'SHARE_A_LINE_SEGMENT_WITH', watershed_lyr)
new_count = int(arcpy.GetCount_management(watershed_lyr).getOutput(0))
if current_count == new_count:
watershed_value = -1
arcpy.AddMessage("No more watersheds")
break
else:
watershed_value += 1
arcpy.AddMessage("At watershed level %i, %i new watersheds found" % (watershed_value, new_count - current_count))
current_count = new_count
data = {"val": watershed_value, "field": calc_attribute}
arcpy.CalculateField_management(watershed_lyr, calc_attribute, "%(val)i if !%(field)s! is None or !%(field)s! == 0 else !%(field)s!" % data, "PYTHON_9.3")
arcpy.AddMessage("Setting base watershed to 0")
arcpy.SelectLayerByAttribute_management(watershed_lyr, "NEW_SELECTION", " %s = -1" % arcpy.AddFieldDelimiters(watershed_lyr, calc_attribute))
arcpy.CalculateField_management(watershed_lyr, calc_attribute, 0)
if __name__ == '__main__':
try:
watershed_counter(*sys.argv[1:])
except Exception, e:
arcpy.AddError(e)
sys.exit(e)
Note that each iteration of the loop in this solution is likely to take a longer amount of time as the size of select by location increases in complexity based on number of features, as well as the number of features to be calculated increasing.
Lastly if you're interested in having multiple possible starting points (ie, shortest destance), remove the assert
in the script.