UpdateCursor takes no arguments

813
8
Jump to solution
09-27-2022 11:14 AM
RudyJamet
New Contributor II

Hello, I have been trying to fill a shapefile with EXIF data from pictures taken by a drone.

I was able to create the shapefile and the desired fields in the attribute table, but I failed to populate the fields with the data. The script below always returns UpdateCursor() takes no arguments.

As I wrote this script with the input from other people on the internet (suggestions and actual scripts), I have no idea what to do next and how to resolve this issue. I welcome any advice and will appreciate the help.

import os
import arcpy
from pathlib import Path

IMAGE_FOLDER = Path(
    r"\\...\InspectionServicesData\DRONE_INSPECTION_SERVICE\01_Projects\...\2_FIELD-WORK\DATA-DUMP\2022-08-13...\DJI_202208131356_022")

img_path = r"\\...\InspectionServicesData\DRONE_INSPECTION_SERVICE\01_Projects\...\2_FIELD-WORK\DATA-DUMP\2022-08-13...\DJI_202208131356_022"
image_path = os.listdir(img_path)

for img in image_path:
    full_image_path = os.path.join(img_path, img)

exif_properties = {}
output_shpdata = r"C:\Users\...\OneDrive...\Desktop\EXIF_TEST\output_shpdata.shp"
shp_data = []
spatial_ref = arcpy.env.outputCoordinateSystem = arcpy.SpatialReference(4326)


for image in IMAGE_FOLDER.glob("*.jpg"):
    exif_properties[image.name] = arcpy.GetImageEXIFProperties(image)

for name in exif_properties:
    target_data = exif_properties[name][3]
    root_path = r"\\...\InspectionServicesData\DRONE_INSPECTION_SERVICE\01_Projects\...\2_FIELD-WORK\DATA-DUMP\2022-08-13..."
    full_path = "".join([root_path, "\\", name])
    targlong = target_data['XMP:drone-dji:LRFTargetLon']
    tarlat = target_data['XMP:drone-dji:LRFTargetLat']
    tardist = target_data['XMP:drone-dji:LRFTargetDistance']
    gimbalyaw = target_data['XMP:drone-dji:GimbalYawDegree']

    shp_data.append([name, tardist, gimbalyaw, full_path, targlong, tarlat])

def output_shpdata_creator():

    pt = arcpy.Point()
    ptGeoms = []

    for p in shp_data:
        pt.X = p[4]
        pt.Y = p[5]

        ptGeoms.append(arcpy.PointGeometry(pt, spatial_ref))

    arcpy.CopyFeatures_management(ptGeoms, output_shpdata)
    arcpy.AddField_management(output_shpdata, "Name", "TEXT", 9, "", "", "refcode", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(output_shpdata, "Distance", "DOUBLE", 9, "", "", "refcode", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(output_shpdata, "YawDegree", "FLOAT", 9, "", "", "refcode", "NULLABLE", "REQUIRED")
    arcpy.AddField_management(output_shpdata, "ImagePath", "TEXT", 9, "", "", "refcode", "NULLABLE", "REQUIRED")
    arcpy.AddXY_management(output_shpdata)

    count = 0

    with arcpy.da.UpdateCursor(output_shpdata, ['Name', 'Distance', 'YawDegree', 'ImagePath']) as cursor:
        for r in cursor:
            r[0] = shp_data[count][0]
            r[1] = shp_data[count][1]
            r[2] = shp_data[count][2]
            r[3] = shp_data[count][3]

            cursor.updateRow(r)

            count += 1

print(shp_data)
output_shpdata_creator()
0 Kudos
1 Solution

Accepted Solutions
JohannesLindner
MVP Frequent Contributor

Hmmm. I couldn't reproduce your error, and I have no idea what could cause it, the UpdateCursor part is OK.

General tips:

  • your lines 8-12 don't do anything
  • you use 4 for loops (lines 20, 23, 39, 55) that basically loop over the same data. you can just do it in 1.

Try using InsertCursor instead:

 

import arcpy
from pathlib import Path

IMAGE_FOLDER = Path(r"\\...\InspectionServicesData\DRONE_INSPECTION_SERVICE\01_Projects\...\2_FIELD-WORK\DATA-DUMP\2022-08-13...\DJI_202208131356_022")

output_path = r"C:\Users\...\OneDrive...\Desktop\EXIF_TEST\"
output_name = "output_shpdata.shp"
spatial_ref = arcpy.env.outputCoordinateSystem = arcpy.SpatialReference(4326)

# create the ouput shape file and add fields
out_shp = arcpy.management.CreateFeatureclass(output_path, output_name, "POINT", spatial_reference=spatial_ref)
arcpy.management.AddField(out_shp, "Name", "TEXT")
arcpy.management.AddField(out_shp, "Distance", "DOUBLE")
arcpy.management.AddField(out_shp, "YawDegree", "FLOAT")
arcpy.management.AddField(out_shp, "ImagePath", "TEXT")
arcpy.management.AddField(out_shp, "Long", "DOUBLE")
arcpy.management.AddField(out_shp, "Lat", "DOUBLE")

# start the InsertCursor
with arcpy.da.InsertCursor(out_shp, ["SHAPE@", "Name", "Distance", "YawDegree", "ImagePath", "Long", "Lat"]) as cursor:
    # loop through the image files
    for image in IMAGE_FOLDER.glob("*.jpg"):
        # extract exif properties
        target_data = arcpy.GetImageEXIFProperties(image)[3]
        long = target_data['XMP:drone-dji:LRFTargetLon']
        lat = target_data['XMP:drone-dji:LRFTargetLat']
        dist = target_data['XMP:drone-dji:LRFTargetDistance']
        gimbalyaw = target_data['XMP:drone-dji:GimbalYawDegree']
        # create the point geometry
        geo_wgs84 = arcpy.PointGeometry(arcpy.Point(long, lat), arcpy.SpatialReference(4326))
        geo = geo_wgs84.projectAs(spatial_ref)
        # insert the values
        row = [geo, image.name, dist, gimbalyaw, str(image), long, lat]
        cursor.insertRow(row)

 


Have a great day!
Johannes

View solution in original post

8 Replies
by Anonymous User
Not applicable

It would help if you used the code formatter (click the ..., then the </> icon to open the window to paste your code)

I would move the pt = arcpy.Point() under the for p in shp_data: loop.  With it being outside of the loop, each iteration is using the same pt and it can be messing things up referencing the same object.

The shapefile gets created with fields, but do the points make it into the fc?  You might have an empty shapefile and nothing for the updateRow() to update.

0 Kudos
RudyJamet
New Contributor II

Hi Jeff, thanks for your reply. The points are created as well, maybe thanks to the function arcpy.AddXY_mangement. I mean, the attribute table shows the long/lat coordinates for all records, and all records/points are displayed. The other fields are empty.

0 Kudos
JohannesLindner
MVP Frequent Contributor

It's very hard to read your script in plain text. Please post it formatted as code:

JohannesLindner_0-1664303901166.png

JohannesLindner_1-1664303911535.png

 


Have a great day!
Johannes
0 Kudos
RudyJamet
New Contributor II

Thanks Johannes for the tip. I had no idea.

0 Kudos
DanPatterson
MVP Esteemed Contributor

and if you need a bookmark for formatting

Code formatting ... the Community Version - Esri Community


... sort of retired...
0 Kudos
JohannesLindner
MVP Frequent Contributor

Hmmm. I couldn't reproduce your error, and I have no idea what could cause it, the UpdateCursor part is OK.

General tips:

  • your lines 8-12 don't do anything
  • you use 4 for loops (lines 20, 23, 39, 55) that basically loop over the same data. you can just do it in 1.

Try using InsertCursor instead:

 

import arcpy
from pathlib import Path

IMAGE_FOLDER = Path(r"\\...\InspectionServicesData\DRONE_INSPECTION_SERVICE\01_Projects\...\2_FIELD-WORK\DATA-DUMP\2022-08-13...\DJI_202208131356_022")

output_path = r"C:\Users\...\OneDrive...\Desktop\EXIF_TEST\"
output_name = "output_shpdata.shp"
spatial_ref = arcpy.env.outputCoordinateSystem = arcpy.SpatialReference(4326)

# create the ouput shape file and add fields
out_shp = arcpy.management.CreateFeatureclass(output_path, output_name, "POINT", spatial_reference=spatial_ref)
arcpy.management.AddField(out_shp, "Name", "TEXT")
arcpy.management.AddField(out_shp, "Distance", "DOUBLE")
arcpy.management.AddField(out_shp, "YawDegree", "FLOAT")
arcpy.management.AddField(out_shp, "ImagePath", "TEXT")
arcpy.management.AddField(out_shp, "Long", "DOUBLE")
arcpy.management.AddField(out_shp, "Lat", "DOUBLE")

# start the InsertCursor
with arcpy.da.InsertCursor(out_shp, ["SHAPE@", "Name", "Distance", "YawDegree", "ImagePath", "Long", "Lat"]) as cursor:
    # loop through the image files
    for image in IMAGE_FOLDER.glob("*.jpg"):
        # extract exif properties
        target_data = arcpy.GetImageEXIFProperties(image)[3]
        long = target_data['XMP:drone-dji:LRFTargetLon']
        lat = target_data['XMP:drone-dji:LRFTargetLat']
        dist = target_data['XMP:drone-dji:LRFTargetDistance']
        gimbalyaw = target_data['XMP:drone-dji:GimbalYawDegree']
        # create the point geometry
        geo_wgs84 = arcpy.PointGeometry(arcpy.Point(long, lat), arcpy.SpatialReference(4326))
        geo = geo_wgs84.projectAs(spatial_ref)
        # insert the values
        row = [geo, image.name, dist, gimbalyaw, str(image), long, lat]
        cursor.insertRow(row)

 


Have a great day!
Johannes
RudyJamet
New Contributor II

It works perfectly! Thanks a lot Johannes, you made my day.

0 Kudos
RudyJamet
New Contributor II

Just another question. I am trying to convert the Python script into a geoprocessing script in ArcGIS Pro. Ideally, it would contain parameters for the user to fill in, like Image Folder and Destination Folder. In the Python script, the parameters would be linked to IMAGE_FOLDER, output_path and output_name. I don't know how to do that.

Also, I thought the result of the geoprocessing would be automatically added to the Contents pane, but it doesn't, even though in Options\Geoprocessing the Add output datasets to an open map is checked.

If you have some suggestions, I would appreciate. Thanks Johannes.

0 Kudos