0

I am a little stuck on my code. I am new to Python and am learning as I go, but have usually been able to figure it out till now. The code was working up till I put the dictionary part in and now this is where its failing. When I run the program, it only goes through once and doesn't appear to be storing the data. I have found people in the discussions have had the same problem, but they never said what helped them resolve the issue. Below is a breakdown of the objective of the program:

The rhinos in the spreadsheet appear in no guaranteed order, and not all the rhinos appear at the beginning of the spreadsheet. As I parse each line, I must determine which rhino the reading belongs to and update that rhino's polyline track accordingly. I am not allowed to sort the Rhino column in Excel before I export to the CSV file. My script must be "smart" enough to work with an unsorted spreadsheet in the order that the records appear.

I do not immediately know how many rhinos are in the file or even what their names are. Although I could visually comb the spreadsheet for this information and hard-code each rhino's name, your script is required to handle all the rhino names programmatically. The idea is that I should be able to run this script on a different file, possibly containing more rhinos, without having to make many manual adjustments.

Sample Data:

Observer,X,Y,Rhino,Comments
Ben,26.99391,-19.10447,Bo,
Ben,27.00071,-19.1089,Tulip,Bathing
Ben,26.9919,-19.10511,Bo,
Ben,27.00071,-19.1059,Tulip,
Ben,26.96809,-19.09578,Patches,
Ben,26.97808,-19.11016,Dinky,
Ben,26.99213,-19.10395,Bo,
Ben,27.00083,-19.10326,Tulip,

I am lost and confused....

#Import a csv file into ArcMap and plot the points for each Rhino
import arcpy
import csv

arcpy.env.workspace = "C:\\GEOG485\\Lesson4\\Project4"
arcpy.env.overwriteOutput = True

targetFolder = "C:\\GEOG485\\Lesson4\\Project4"
rhinoShape = "C:\\GEOG485\\Lesson4\\Project4\\Rhino.shp"
rhinoFile = "C:\\GEOG485\\Lesson4\\Project4\\RhinoObservations.csv"
spatialRef = arcpy.Describe(rhinoShape).spatialReference

try:
    #Open CSV file and read the headers

    trackPoints = open(rhinoFile, "r")
    textLine = trackPoints.readline()
    headerLine = textLine.strip("\n")    
    pairList = headerLine.split(",")
    print pairList
    polylineArray = arcpy.Array()
    #Get index for header fields
    xIndex = pairList.index("X")
    yIndex = pairList.index("Y")
    rhinoIndex = pairList.index("Rhino")
    print rhinoIndex

    #Created an empty dictionary
    dictionaryRhinoTracks = {}

    for line in trackPoints.readlines():
        line = line.rstrip("\n")
        splitLine = line.split(",")
        print splitLine
        #Created variable for needed field items based on index location
        pointX = splitLine[xIndex]
        pointY = splitLine[yIndex]
        rhinoName = splitLine[rhinoIndex]

        #Create a point object

        currentPoint.x = pointX
        currentPoint.y = pointY
        currentPoint = arcpy.Point(currentPoint.x, currentPoint.y)
        print currentPoint

        #Check if the dictionary does not contain name
        if rhinoName not in dictionaryRhinoTracks:
            rhinoTrackArray = polylineArray.Add(currentPoint)
            #Add the point object to the Array
            dictionaryRhinoTracks[rhinoName].Add(currentPoint)


    cursor = arcpy.da.InsertCursor(rhinoShape, ['SHAPE@'])
    cursor.insertRow([polyline])

    for rhinoName in dictionaryRhinoTracks:   
        row.Shape = dictionaryRhinoTracks[rhinoName]
        row.Rhino_Name = rhinoName
        cursor.InsertRow(row)

except:
    print ("error again")
  • 3
    Welcome to GIS SE. As a new user, please take the Tour. Using a huge try block is often a good way to hide errors from debugging attempts. I suggest adding more print statements, so you can follow the program logic, then report the debug output and error message in this question. – Vince Apr 11 at 22:19
  • 4
    As @Vince suggests, lose the try...except and please post the stack trace along with your question to make it easier for people to help. Also, because this is a homework question be aware that people will likely help with the specific problem, but won't answer the whole question for you! – om_henners Apr 11 at 22:32
5

Don't use try:...except: when debugging. Don't use silent and overly broad exception handling ever.

Some comments:

  1. You're not using the csv module. You import it, then never use it, instead you manually read and parse the file as text.
  2. arcpy.Array doesn't have an Add method, it has an add method - python is case-sensitive
  3. You're mixing the old arcpy.InsertCursor and arcpy.da.InsertCursor syntax. Avoid arcpy.InsertCursor, use arcpy.da.InsertCursor.
  4. arcpy.da.InsertCursor doesn't have an InsertRow method, it has an insertRow method - python is case-sensitive
  5. You use a polyline variable which isn't defined anywhere
  6. You don't create an arcpy.Polyline anywhere
  7. You try to use currentPoint before you actually define it
  8. Your X and Y values are strings, they need to be floats.

You would have seen error messages about 2 - 8 if you had not used try: except: and hidden them.

So... even though I think this is a homework question... You've had a good try at answering it yourself, so here is how I would do it.

First, I'd use the CSV module and a DictReader to make life easy. Then I'd use a defaultdict so I don't have to check whether a Rhino is already in the dict. Don't forget to check out how to use an arcpy.da.InsertCursor and consider using with statements so your open files and Insert/UpdateCursors get cleaned up automatically.

from collections import defaultdict
import csv
import arcpy

target_folder = 'etc...'
rhino_shape = 'etc...'
rhino_file = 'etc...'

rhino_tracks = defaultdict(arcpy.Array)

with open(rhino_file) as csvfile:
    reader = csv.DictReader(csvfile)
    for row in reader:
        point = arcpy.Point(float(row['X']), float(row['Y']))
        rhino_tracks[row['Rhino']].add(point)

with arcpy.da.InsertCursor(rhino_shape, ['SHAPE@', 'Rhino']) as rows:  # Assume a shapefile with a 'Rhino` text field
    for rhino, array in rhino_tracks.items():
        polyline = arcpy.Polyline(array)
        rows.insertRow([polyline, rhino])
  • Thanks for the advice and help. This is a homework question that has had me stumped for a few days now. Now I can't add a text field into the shapefile in advance, so would I create the field in the program? That way when it runs it will put "Rhino" into the shapefile? – Will Apr 12 at 1:58
  • 1
    If the shapefile exists, you can check for a "Rhino" field with if "RHINO" in [f.name.upper() for f in arcpy.Describe(rhino_shape).fields]: and use arcpy.AddField_management to add a Rhino field if not. – user2856 Apr 12 at 2:10
  • I think this is a great answer highlighting classic "school boy" errors. Your 8 point list of the problems really show that one must be methodical in developing code, understand data types and understand the nuisances of the chosen language (in this case Python). – Hornbydd Apr 12 at 9:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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