Select to view content in your preferred language

Looping Select by Attribute, ADDING one by one feature each time, and run a tool

1468
6
03-26-2014 12:15 PM
RafaelRuas_Martins
Occasional Contributor
Hi!
I am new w/ ArcPy! I am having some dificulties to create a simple workflow to create an "Accumulative Curve":
1) A point feature class as input;
2) Select the first 3 points based on a table field (ObjectID, for exe.);
3) Apply Minumun Boundary Geometry tool w/ Convex_Hull option, on those selected points;
4) Add a field on the output and calculate shape area in hectares;
5) Write a txt file, w/ two coluns: n. of selected points and Shape Area value;

At this point OK as you can see in the script above.
From now, I have no idea how to integrate LOOP and SELECT!!!

6) Select the first 3 points as step 2, and ADD the fourth feature on the selection;
7) Repeat steps 3, 4, and 5.
😎 ADD the fifth feature on selection;
9) Repeat steps 3, 4, and 5.

As you can see, I´d like to have a TXT file, w/ two coluns, the first one to show the number of selected points and the another one to show area value, in hectares!!!

That´s what I could do!!!!

# Import arcpy module and set the current workspace
# Set the overwriteOutput environment setting to True
import arcpy
arcpy.env.workspace = r"C:/TESTE_py/AccumCurve.gdb"
arcpy.env.overwriteOutput = True

# Create a inputFC feature layer
arcpy.MakeFeatureLayer_management ("Bandaid", "Bandaid_lyr")

# Select the first 3 points based on OBJECTID field values
SQLExp = '"OBJECTID" IN (1,2,3)'
selected = arcpy.SelectLayerByAttribute_management ("Bandaid_lyr", "NEW_SELECTION", SQLExp)

# Get count the number of selected points
count = arcpy.GetCount_management (selected)
print str(count) + " points"

# Execute Minimum Bounding Geometry Tool (Convex Hull) over selection
arcpy.MinimumBoundingGeometry_management ("Bandaid_lyr","MCP_3", "CONVEX_HULL")

# Add field and calculate area (hectares)
arcpy.AddField_management ("MCP_3", "HECTARES", "Float")

with arcpy.da.UpdateCursor ("MCP_3", ["Shape_Area", "HECTARES"]) as cursor:
    for row in cursor:
        geom = row[0]
        row[1] = geom / 10000
        cursor.updateRow(row)

# Read and create a variable w/ the area value from MCP_3 feature class
fc = r"C:/TESTE_py/AccumCurve.gdb/MCP_3"
field = "HECTARES"
rows = arcpy.SearchCursor(fc)
for row in rows:
    area_value = (row.getValue(field))
    print str(area_value) + " hectares"
   
# Write a TXT file, w/ 2 colunms: n. of points (count) and hectares
txtFile = open("C:/TESTE_py/MCP_3.txt", "w")
txtFile.write("Count ; Area_Value" + "\n")
line = "{0} ; {1}".format (count, area_value)
txtFile.write(line)

# Close the text file
txtFile.close()

print "Script completed"

Tks for some help!!!
Tags (2)
0 Kudos
6 Replies
FilipKrál
Frequent Contributor
Hi rafaelruas,
If I understood correctly what you want to do, the code below should work for you.

# The code below adds one point at a time to a selection and
# calculates area of convex hull of the selection.
# Output is a text file (or table) with with two columns.
# First column holds number of points selected,
# second column holds total area of the hull.
# Provided you want to use all points in the feature class.
# I recommend you use square metres to get the area and do
# the conversion yourself if you need to. If square metres
# result in too large numbers, use square kilmetres.

import arcpy

# PARAMETERS

in_points = r'C:\temp\base.gdb\pts'

# column indicating in what order to add points to the curve
# should be integers from 1 to N by 1
sort_field = 'OBJECTID'

out_results = r'c:\temp\results.txt'
out_delim = ","

# we need to store the hull temporarily;
# there are more ways how to deal with intermediate data, this is a simple one
arcpy.env.overwriteOutput = True
tmp_hull = r'c:\temp\hull.shp'


# WORK

# write header for result file
with open(out_results, "w") as fl:
    header = out_delim.join(("PT_COUNT", "M_SQ"))
    fl.write(header + "\n")

# total number of points
n = int(arcpy.GetCount_management(in_points).getOutput(0))

# we need a feature layer in order to make quick selections
in_points_lyr = arcpy.management.MakeFeatureLayer(in_points, "points").getOutput(0)

for i in range(n):
    print i
    # add another point to the selecition
    w_clause = '"%s" < %s' % (sort_field, i + 1) # e.g. OBJECTID < 1, OBJECTID < 2, ...
    arcpy.management.SelectLayerByAttribute(in_points_lyr, "NEW_SELECTION", w_clause)

    # counstruct convex hull
    hull = arcpy.management.MinimumBoundingGeometry(in_points_lyr, tmp_hull, "CONVEX_HULL", "ALL").getOutput(0)

    # get the area of the convex hull
    # (if you coordinate system units are metres)
    ara = 0
    with arcpy.da.SearchCursor(hull, ["SHAPE@AREA"]) as sc:
        for row in sc:
            ara += row[0] # should be just one row anyway

    # write results for i into the result file
    with open(out_results, "a") as fl:
        result = out_delim.join((str(i + 1), str(ara)))
        fl.write(result + "\n")

print("Script completed.")

# if you want to import the text file into ArcGIS, do
arcpy.management.CopyRows(out_results, r"c:\temp\results.dbf")


Hope this helps,
Filip.
0 Kudos
RafaelRuas_Martins
Occasional Contributor

Hi!!!! 

Could you help me again w/ the same code, please???

I have been using it w/ no problem since I up graded ArcGIS Desktop from 10.3 to 10.4.

 

# The code below adds one point at a time to a selection and
# calculates area of convex hull of the selection.
# Output is a text file (or table) with with two columns.
# First column holds number of points selected,
# second column holds total area of the hull.
# Provided you want to use all points in the feature class.
# I recommend you use square metres to get the area and do
# the conversion yourself if you need to. If square metres
# result in too large numbers, use square kilmetres.
 
import arcpy
 
# PARAMETERS
 
in_points = arcpy.GetParameterAsText(0)
 
# column indicating in what order to add points to the curve
# should be integers from 1 to N by 1
sort_field = 'OBJECTID'
 
out_results = arcpy.GetParameterAsText(1)
out_delim = ","
 
# we need to store the hull temporarily;
# there are more ways how to deal with intermediate data, this is a simple one
arcpy.env.overwriteOutput = True
tmp_hull = arcpy.GetParameterAsText(2)
 
 
# WORK
 
# write header for result file
with open(out_results, "w") as fl:
header = out_delim.join(("PT_COUNT", "M_SQ"))
fl.write(header + "\n")
 
# total number of points
n = int(arcpy.GetCount_management(in_points).getOutput(0))
 
# we need a feature layer in order to make quick selections
in_points_lyr = arcpy.management.MakeFeatureLayer(in_points, "points").getOutput(0)
 
for i in range(n):
print i
# add another point to the selecition
w_clause = '"%s" < %s' % (sort_field, i + 1) # e.g. OBJECTID < 1, OBJECTID < 2, ...
arcpy.management.SelectLayerByAttribute(in_points_lyr, "NEW_SELECTION", w_clause)
 
# counstruct convex hull
hull = arcpy.management.MinimumBoundingGeometry(in_points_lyr, tmp_hull, "CONVEX_HULL", "ALL").getOutput(0)
 
# get the area of the convex hull
# (if you coordinate system units are metres)
ara = 0
with arcpy.da.SearchCursor(hull, ["SHAPE@AREA"]) as sc:
for row in sc:
ara += row[0] # should be just one row anyway
 
# write results for i into the result file
with open(out_results, "a") as fl:
result = out_delim.join((str(i + 1), str(ara)))
fl.write(result + "\n")
 
print("Script completed.")
 
 
That's the error message!!!

Why that error??? 

0 Kudos
FilipKrál
Frequent Contributor

Hi, 

Hmmm, strange. A few things I can think of:

Make sure that in_points actually has the sort_field. For example shapefiles usually don't have OBJECTID.

Try to modify the expression to w_clause = '%s < %s' % (sort_field, i + 1)

I hope you'll find where the problem is.

F.

0 Kudos
DanPatterson_Retired
MVP Emeritus

Shapefiles use FID and begin at 0... geodatabase is OBJECTID (do they begin at 1? can't remember)

0 Kudos
DarrenWiens2
MVP Alum

Rather than hard-coding the name of the OID/FID (sort_field = 'OBJECTID'), you can get it dynamically by describing the data:

sort_field = arcpy.Describe(in_points).OIDFieldName
0 Kudos
RafaelRuas_Martins
Occasional Contributor
Hi Filip.
Such a great job!!!
Thanks so much!!! 100000x tks.
Regards
Rafael
0 Kudos