-2

This question arises from Performing Point Distance analysis using Basic level license of ArcGIS for Desktop?.

I basically copied and pasted PolyGeo's answer and formatted it into a python toolbox that has input parameters. I tried running it with two feature classes that are points. It creates the table but doesn't populate it due to an error. Below is the code to the toolbox. Below that is the error message that is returned.

import arcpy
import math

'''Do not change the name of this class. It will break the toolbox.'''
class Toolbox(object):
def __init__(self):
    '''Define toolbox properties (the toolbox anme is the .pyt filename).'''
    self.label = "Toolbox"
    self.alias = ""

    # List of tool classes associated with this toolbox
    self.tools = [Tool]

class Tool(object):
def __init__(self):
    '''Define the tool (tool name is the class name).'''
    self.label = "Tool"
    self.description = ""
    self.canRunInBackground = False

def getParameterInfo(self):
    '''parameter definitions for GUI'''
    ptFC1 = arcpy.Parameter(
        displayName="Input 1st Point FC",
        name="ptFC1",
        datatype="DEFeatureClass",
        parameterType="Required",
        direction="Input")

    ptFC2 = arcpy.Parameter(
        displayName="Input 2nd Point FC",
        name="ptFC2",
        datatype="DEFeatureClass",
        parameterType="Required",
        direction="Input")

    outGDB = arcpy.Parameter(
        displayName="Output where the table goes",
        name="outGDB",
        datatype="DEWorkspace",
        parameterType="Required",
        direction="Input")

    params = [ptFC1, ptFC2, outGDB]
    return params

def isLicensed(self):
    '''Set whether tool is licensed to execute.'''
    return True

def updateParameters(self, parameters):
    '''Modify the values and properties of parameters before internal
    validation is performed.  This method is called whenever a parameter
    has been changed.'''
    return

def updateMessages(self, parameters):
    '''Modify the messages created by internal validation for each tool
    parameter.  This method is called after internal validation.'''
    return

def execute(self, parameters, messages):
    '''The source code of the tool.'''

    ptFC1 = parameters[0].valueAsText
    ptFC2 = parameters[1].valueAsText
    outGDB = parameters[2].valueAsText

    # Set variables for input point feature classes and output table
    outTableName = "outTable"
    outTable = outGDB + "/" + outTableName

    arcpy.env.overwriteOutput = True

    # Create empty output table
    arcpy.CreateTable_management(outGDB,outTableName)
    arcpy.AddField_management(outTable,"INPUT_FID","LONG")
    arcpy.AddField_management(outTable,"NEAR_FID","LONG")
    arcpy.AddField_management(outTable,"DISTANCE","DOUBLE")

    # Create and populate two dictionaries with X and Y coordinates for each
    # OBJECTID in second feature class using a SearchCursor
    ptFC2XCoordDict = {}
    ptFC2YCoordDict = {}
    with arcpy.da.SearchCursor(ptFC2,["OBJECTID","SHAPE@XY"]) as cursor:
        for row in cursor:
            ptFC2XCoordDict[row[0]] = row[1][0]
            ptFC2YCoordDict[row[0]] = row[1][1]

    # Open an InsertCursor ready to have rows written for each pair of OBJECTIDs
    iCursor = arcpy.da.InsertCursor(outTable,["INPUT_FID","NEAR_FID","DISTANCE"])
    # Use a SearchCursor to read the rows (and X,Y coordinates) of the first
    # feature class
    with arcpy.da.SearchCursor(ptFC1,["OBJECTID","SHAPE@XY"]) as cursor:
        for row in cursor:
            x1 = row[1][0]
            y1 = row[1][1]
            for i in range(len(ptFC2XCoordDict)):
                x2 = ptFC2XCoordDict[i+1]
                y2 = ptFC2YCoordDict[i+1]
                # Prepare and insert the InsertCursor row
                iRow = [row[0],i+1,math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1))]
                iCursor.insertRow(iRow)
    del iCursor


    return

Here is the Error that displays. enter image description here

Line 123 is this: x2 = ptFC2XCoordDict[i+1]

1

This bit looks to have been incorrectly copied:

with arcpy.da.SearchCursor(ptFC2,["OBJECTID","SHAPE@XY"]) as cursor:
    for row in cursor:
        ptFC2XCoordDict[row[0]] = row[1][0]
        ptFC2YCoordDict[row[0]] = row[1][2]

It should be:

with arcpy.da.SearchCursor(ptFC2,["OBJECTID","SHAPE@XY"]) as cursor:
    for row in cursor:
        ptFC2XCoordDict[row[0]] = row[1][0]
        ptFC2YCoordDict[row[0]] = row[1][1]

On the last of these four lines you were trying to set the ptFC2YCoordDict dictionary using a non-existent third ([2]) part to the tuple of X,Y coordinates that the SHAPE@XY provides you with access to.

  • That's weird. In my Pyscripter it has like: with arcpy.da.SearchCursor(ptFC2,["OBJECTID","SHAPE@XY"]) as cursor: for row in cursor: ptFC2XCoordDict[row[0]] = row[1][0] ptFC2YCoordDict[row[0]] = row[1][1] I've updated the code above to reflect the copy error. – MjonesGEO Nov 14 '14 at 21:30
  • This answer has some advice on debugging Python toolboxes gis.stackexchange.com/a/115376/115 – PolyGeo Nov 14 '14 at 23:03
  • I don't think it's a debugging issue with the toolbox. I ran the code from the original without adding the parameters and it still gives me the same error message. – MjonesGEO Nov 14 '14 at 23:06
  • I just re-ran the original script from IDLE and it ran without error. If you are happy to eliminate your Python Toolbox from suspicion and write a new question around the error you are seeing from the code I wrote in the original Q&A then that is something that will be easier to assist with. That code is still more than the snippets which we prefer to work with here but at least it is code that has already been worked through by a few people. – PolyGeo Nov 15 '14 at 0:33
  • Were your two shape files just points? – MjonesGEO Nov 15 '14 at 23:52

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