I currently have a script that allows me to use a mouse click and create points on a map of where there are animal sightings and works great.
But i would like to update the attributes of the points that i create when using the script. I have found a similar script but the script i found only updates the points attributes one at a time. The script that i am working on would allow me to click on a map at different locations in one session and update the points attributes, but the points may not be on the same parcel.
With the help of Darren Wiends and the use Wes MIller scipt i have put together the following but i don't know how to change it to update more then one point at a time. help please.
Re: populate x, y on mouse click
I get the following error with my modified version of Wes Miller code.
Traceback (most recent call last):
File "C:\GIS\Python\AddPoint\AddPoint_6.py", line 47, in <module>
insCursor.insertRow(row)
TypeError: sequence size must match size of the row
current code.
#import modules import arcpy arcpy.env.qualifiedFieldNames = False pointFC = "Animal Sightings" #target point feature class Animal Sightings parcel = "par" parcel_lyr = 'parcel_lyr' mxd = arcpy.mapping.MapDocument("CURRENT") df = arcpy.mapping.ListDataFrames(mxd)[0] dfsr = df.spatialReference fcsr = arcpy.Describe(pointFC).spatialReference if dfsr.name == fcsr.name: """Now do your work""" point = arcpy.GetParameterAsText(0) #click for prow in arcpy.da.SearchCursor(point,'SHAPE@XY'): x,y = prow[0] del prow point1 = arcpy.Point(x, y) ptGeometry = arcpy.PointGeometry(point1) arcpy.MakeFeatureLayer_management(parcel,parcel_lyr) arcpy.SelectLayerByLocation_management(parcel_lyr,"INTERSECT",ptGeometry) insCursor = arcpy.da.InsertCursor(pointFC,'SHAPE@XY') # create insert cursor fldList = ['Owner','SiteAddress',] fldDict ={} #Check that we only have one parcel and get the attributes from it if int(arcpy.GetCount_management(parcel_lyr).getOutput(0))>=1: for parrow in arcpy.da.SearchCursor(parcel_lyr,fldList): for w in range(len(fldList)): fldDict[fldList]=parrow del parrow targetFields = ['Owner', 'SiteAddress', 'POINT_X', 'POINT_Y','SHAPE@XY'] with arcpy.da.SearchCursor(pointFC,targetFields) as cursor: # loop through feature set for row in cursor: row = [] row.append(fldDict['Owner']) row.append(fldDict['SiteAddress']) row.append(x) row.append(y) row.append(point1) insCursor.insertRow(row) del insCursor # delete insert cursor
In the schema option feeding your Feature Set in the point = arcpy.GetParameterAsText(0) # Click, can you configure the underlying Feature Template to set the default attributes to what you want, e.g. default animal = "lion", default color = "yellow", etc.
Is this what you mean by "update all the attributes" - setting the default attributes?
John thank you for the reply.
we track coyotes\wolves across a state so creating multiple points on once and populating those points is very important and save me a lot of time so i don't have to manually enter the info one by one. Along with creating multiple points i need to be able to populate the points with certain information from county's assessment data, like the owner of the property, their address and other information so we can contact the land owner about the coyotes\wolves on there property. I have looked in to the the Template suggestion but it will not populate information that i need from the county's assessment data.
It would be really grateful if someone could help me out with some code, i might be approaching this incorrectly.
I tied change my code, i am close i don't get an error but the only thing that gets populated is the X,Y for each point.
Current code, i have pieced some of these codes from other codes the best why i can. i really appreciate some help please...
#import modules import arcpy arcpy.env.qualifiedFieldNames = False pointFC = "Animal Sightings" #target point feature class Animal Sightings parcel = "par" parcel_lyr = 'parcel_lyr' mxd = arcpy.mapping.MapDocument("CURRENT") df = arcpy.mapping.ListDataFrames(mxd)[0] dfsr = df.spatialReference fcsr = arcpy.Describe(pointFC).spatialReference if dfsr.name == fcsr.name: """Now do your work""" point = arcpy.GetParameterAsText(0) #click for prow in arcpy.da.SearchCursor(point,'SHAPE@XY'): x,y = prow[0] del prow point1 = arcpy.Point(x, y) ptGeometry = arcpy.PointGeometry(point1) rows = arcpy.UpdateCursor(point) for row in rows: feat = row.getValue("shape") cent = feat.centroid row.POINT_X = cent.Y row.POINT_Y = cent.X rows.updateRow(row) arcpy.MakeFeatureLayer_management(parcel,parcel_lyr) arcpy.SelectLayerByLocation_management(parcel_lyr,"INTERSECT",ptGeometry) fldList = ['Owner','Site'] fldDict ={} #Check that we only have one parcel and get the attributes from it if int(arcpy.GetCount_management(parcel_lyr).getOutput(0))>=1: for parrow in arcpy.da.SearchCursor(parcel_lyr,fldList): for w in range(len(fldList)): fldDict[fldList]=parrow del parrow targetFields = ['Owner', 'Site', 'POINT_X', 'POINT_Y','SHAPE@XY'] insCursor = arcpy.da.InsertCursor(pointFC, ('Owner', 'Site','POINT_X', 'POINT_Y','SHAPE@XY')) # create insert cursor with arcpy.da.InsertCursor(pointFC, ('Owner', 'Site','POINT_X', 'POINT_Y','SHAPE@XY')) as cursor: with arcpy.da.SearchCursor(point, targetFields) as s_cursor: for s_row in s_cursor: cursor.insertRow(s_row) del cursor
Here's another approach for you to consider. It involves three steps after you enter your points.
I found a script (with some explanation) here that does part of the process. All that was needed was getting the x and y data. The script overwrites the spatial join each time it is run. If field names are the same in both point and polygon layers, you may need to append a "_1" to field names. I ran a spatial join to see how the field names were created and then adjusted the script. The script can be run outside of ArcMap; close the map/layers to avoid any schema locks.
# Import arcpy module import arcpy # scratch spatial join feature sjpoints = r"C:\path\to\geodatabase.gdb\test_join" # define the field list from the spatial join to transfer # you can add more field names such as: ["TARGET_FID", "Field", "AnoterField"] sourceFieldsList = ["TARGET_FID", "Field"] # point feature that will be updated pointLayer = r"C:\path\to\geodatabase.gdb\point_fc" # polygon feature that will be used polygonLayer = r"C:\path\to\geodatabase.gdb\poly_fc" # define the field list to the original points updateFieldsList = ["OID@", "xferField"] # Allow overwrite of join results arcpy.env.overwriteOutput = True #Run the Spatial Join tool, using the defaults for the join operation and join type arcpy.SpatialJoin_analysis(pointLayer, polygonLayer, sjpoints) # populate the dictionary from the polygon valueDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(sjpoints, sourceFieldsList)} with arcpy.da.UpdateCursor(pointLayer, updateFieldsList) as updateRows: for updateRow in updateRows: keyValue = updateRow[0] if keyValue in valueDict: for n in range (1,len(sourceFieldsList)): updateRow= valueDict[keyValue][n-1] updateRows.updateRow(updateRow) del valueDict # Use AddGeometryAttributes to set Point_X and Point_Y # SpatialReference("WGS 1984") to display in Lat-Long arcpy.AddGeometryAttributes_management(Input_Features = pointLayer, Geometry_Properties="POINT_X_Y_Z_M", Length_Unit="", Area_Unit="", Coordinate_System=arcpy.SpatialReference("WGS 1984"))
Randy i have a script that is pretty much identical to the one you posted. It currently only works for existing points. The script i am looking to build would create multiple points and uses dictionaries and list, they seem to run faster then actual joins. I am having a hard time coming up with the correct code to create multiple points. I do appreciate the response and suggestion.
Hi Randy,
I've adapted the script you suggested and I'm getting the following error
Traceback (most recent call last):
File "S:/Scripts/ShortRecyclingAuditUpdate.py", line 41, in <module>
updateRows.updateRow(updateRow)
TypeError: sequence size must match size of the row
Here is the script
import arcpy
arcpy.env.workspace = "\\\\Projects\\RecyclingAudit\\RecyclingAuditUpdate"
PW = "\\\\Projects\\RecyclingAudit\\RecyclingAuditUpdate\\UpdateAudits.gdb"
RecyDistrict = "\\\\connections\\SDELOAD@Pub.sde\\RecyclingDistrict"
RecyAudit = PW +"\\RecyclingAudit"
RecyAuditFieldList = ["Week","RecycleRt","RecyCollDay"]
SpatialJoin = PW + "\\SpatialJoin_RA"
SpatialJoinFields = ["Week", "RecycleRt", "RecyCollDay"]
arcpy.env.overwriteOutput = True
if arcpy.Exists(SpatialJoin):
arcpy.Delete_management(SpatialJoin)
# Scratch spatial join feature
arcpy.SpatialJoin_analysis(RecyAudit, RecyDistrict, SpatialJoin, "JOIN_ONE_TO_ONE", "KEEP_ALL",
'Crdt "Crdt" false true false 8 Date 0 0,First,#,RecyclingAudit,Crdt,-1,-1;'
'Address1 "address" true true false 255 Text 0 0,First,#,RecyclingAudit,Address1,0,255;'
'Classification "Classification" true true false 255 Text 0 0,First,#,RecyclingAudit,Classification,0,255;'
'Status "Status" true true false 10 Text 0 0,First,#,RecyclingAudit,Status,0,10;'
'Compliance "Compliance" true true false 5 Text 0 0,First,#,RecyclingAudit,Compliance,0,5;'
'Week "Week" true true false 50 Text 0 0,First,#,SolidWasteRecyclingDistrict,Week,0,50;'
'RecycleRt "RecycleRt" true true false 50 Text 0 0,First,#,SolidWasteRecyclingDistrict,RecycleRt,0,50;'
'RecyCollDay "RecyCollDay" true true false 50 Text 0 0,First,#,SolidWasteRecyclingDistrict,RecyCollDay,0,50',
"INTERSECT", None, '')
# Start edit session
edit = arcpy.da.Editor(PW)
edit.startEditing(True, False)
edit.startOperation()
# Populate the dictionary from recycling district
valueDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(SpatialJoin, SpatialJoinFields)}
with arcpy.da.UpdateCursor(RecyAudit, RecyAuditFieldList) as updateRows:
for updateRow in updateRows:
keyValue = updateRow[0]
if keyValue in valueDict:
for n in range (1,len(SpatialJoinFields)):
updateRow = valueDict[keyValue][n-1]
updateRows.updateRow(updateRow)
del valueDict
# Stop edit operation, stop edit session and save changes
edit.stopOperation()
edit.stopEditing(True)
This is what the tables look like
Could you please help me understand what the error means?
I don't understand how the update cursor knows which records to update. As you can see from the table I only need to update the records that are NULL.
Thanks.