Select to view content in your preferred language

difficulty calculating field in Python

2472
2
05-02-2014 11:54 AM
JasonTrook
Deactivated User
Hi All,
I'm having difficulty calculating a field in my Python script.  I have a bunch of polylines and I want to get the azimuth for each line in degrees.
This is where my code crashes (the math module has already been imported):

fieldName3 = "Azimuth"
expression2 = "180+math.atan2(( !Shape.firstpoint.X! - !Shape.lastpoint.X! ),( !Shape.firstpoint.Y! - !Shape.lastpoint.Y! ) ) * (180 / math.pi )"
arcpy.CalculateField_management(outFeatureClass, "Azimuth", expression2, "PYTHON")  


I get an arcgisscripting.ExecuteError: ERROR 000539:
The confusing thing is I can paste the same code in the field calculator and it works fine.

Thanks in advance for you help,
Jason
Tags (2)
0 Kudos
2 Replies
KimOllivier
Honored Contributor
I suggest you do not use the CalculateField tool in a Python script.

It is much better to use an UpdateCursor which is just as fast or faster because CalculateField wraps a cursor around the expression anyway.

You can also handle unexpected input such as null values, put in conditional tests and generally make the process more readable.

But answering your question, it looks like you have the exclamation marks around the whole expression, not just the field name, so I am very surprised that it works interactively at all.

fieldName3 = "Azimuth"
expression2 = "180+math.atan2(( !Shape!.firstpoint.X - !Shape!.lastpoint.X ),( !Shape!.firstpoint.Y - !Shape!.lastpoint.Y ) ) * (180 / math.pi )"
arcpy.CalculateField_management(outFeatureClass, "Azimuth", expression2, "PYTHON")
0 Kudos
MattEiben
Deactivated User
Here's one method I put together for this.  I'm not sure if there's a built in method in arcpy's Geometry object to get bearing or not.  In my case, I pulled all the coordinates out of the geometry object into a list.  Then iterated through the list, using a little trigonometry to get the bearings.

My formulate was adapted from here:
http://www.movable-type.co.uk/scripts/latlong.html

def getBearing(latFrom,lonFrom,latDest,lonDest):
    # Returns the initial bearing in degrees from north following the great
    # circle path to the destination coordinates.
    lat1 = math.radians(float(latFrom))
    lat2 = math.radians(float(latDest))

    dLon = math.radians(float(lonDest)-float(lonFrom))

    y = math.sin(dLon) * math.cos(lat2)

    x = math.cos(lat1) * math.sin(lat2) - \
        math.sin(lat1) * math.cos(lat2) * math.cos(dLon)

    brng = math.atan2(y, x)

    return (math.degrees(brng) + 360) % 360;


line_coordinates = []
# Get your geometry object
geoms = [row[0] for row in arcpy.da.SearchCursor(yourFeature_Class,["SHAPE@"])]

# Iterate through all the points in your geomtry, appending them to the "line_coordinates" list
for geom in geoms:

    partCount = geom.partCount

    for n in xrange(partCount):
        part = geom.getPart(n)
        for point in part:
            line_coordinates.append((point.Y, point.X))

# Iterate through the "line_coordinates" list, printing the bearings
n = 1
while n < len(line_coordinates):
    print "%0.4f" % getBearing(line_coordinates[n-1][0],line_coordinates[n-1][1],line_coordinates[0],line_coordinates[1])
    n += 1


This method may be a little roundabout, but it's gotten it done for me in the past.  Worth noting though, that the bearing is from the starting coordinate, as bearing may change along a longer great circle.
0 Kudos