Update points attributes based on there location.

3138
6
07-30-2015 08:09 AM
PacoAlverez
New Contributor III

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
0 Kudos
6 Replies
JohnTran1
New Contributor II

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?

0 Kudos
PacoAlverez
New Contributor III

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.

0 Kudos
PacoAlverez
New Contributor III

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
0 Kudos
RandyBurton
MVP Regular Contributor

Here's another approach for you to consider.  It involves three steps after you enter your points.

  1. Do a spatial join with the points and polygon features.
  2. Copy the fields from the join output to your point layer.
  3. Populate the Point_X and Point_Y fields in your point layer.

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"))
PacoAlverez
New Contributor III

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.

0 Kudos
AliciaShyu
Occasional Contributor

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

SpatialJoin.png

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.

0 Kudos