Select to view content in your preferred language

Field Calculate values from a field in another layer brought in from spatial join

992
2
06-08-2023 01:58 PM
AFackler_NAPSG
Frequent Contributor

Hello all, so here's what I am looking at doing:

So I have a handful of photos that I run a geotag photo to point and I want to put the team name into the point attributes of those photos. Part of our workflow is when the team goes out they populate a "UAS Operating Zone" polygon using field maps (an AGOL feature layer) and what I want to do is take the team name field from the operating zone and put it into all the points' team name field mostly so we aren't duplicating efforts. The idea is if I get this working I can duplicate for the rest of the fields in the points layer. To manually do this workflow is a simple spatial join and field calculate, but it is proving to be more complicated when I do it in Python. The end goal is to make this into a script in a toolbox so anyone can use it. Below is my code so far and I'm getting the error "Invalid field UASTemp_AddSpatialJoin_11.team_name Failed to execute (CalculateField). I'm also not really sure if the spatial join is working, I am just assuming so since the error I am getting is coming from the field calculation. I took out the field mapping part parameter on the script below on the join just to make things easier to read on here but can add it back in if needed. Let me know what I'm missing and if there are any workaround. I am running ArcGIS Pro 3.1.2.

import os
import arcpy
from sys import argv
from datetime import date
from pathlib import Path
project = arcpy.mp.ArcGISProject("Current")
m = project.activeMap
# All the parameters pulled in from user inputs
InputFolder = arcpy.GetParameterAsText(0)
today = date.today().strftime('%Y%m%d')
#Finds where the script is located and backs up to the root folder, that way the script can find the UAS geodatabase
full_path = os.path.dirname(__file__)
env = Path(full_path).parents[0]
# Name the feature class
OutputFeatureClass = r"{}\incident_data\imagery\2023_UAS_photos.gdb\UASTemp".format(env)
# Geotagged Photos to Points
arcpy.management.GeoTaggedPhotosToPoints(InputFolder , OutputFeatureClass , None, "ONLY_GEOTAGGED", "ADD_ATTACHMENTS")

m.addDataFromPath(OutputFeatureClass)
# Add and Calc TEAM NAME
arcpy.management.AddField(
in_table=OutputFeatureClass,
field_name="team_Name",
field_type="TEXT",
field_precision=None,
field_scale=None,
field_length=255,
field_alias="Team",
field_is_nullable="NULLABLE",
field_is_required="NON_REQUIRED",
field_domain="")

# Join
arcpy.management.AddSpatialJoin(
    target_features=OutputFeatureClass,
    join_operation="JOIN_ONE_TO_ONE",
    join_type="KEEP_ALL",
    field_mapping=
    match_option="WITHIN",
    search_radius=None,
    distance_field_name=""
)
arcpy.management.CalculateField(
    in_table=OutputFeatureClass,
    field="{}.team_Name".format(OutputFeatureClass),
    expression="!UASTemp_AddSpatialJoin_11.team_name!",
    expression_type="PYTHON3",
    code_block="",
    field_type="TEXT",
    enforce_domains="NO_ENFORCE_DOMAINS"
)
0 Kudos
2 Replies
JoshuaSharp-Heward
Frequent Contributor

Hi,

It sounds like the field name you're using as the input doesn't match any fields in your input table. I'd try commenting the field calculator out and putting

fields = [f.name for f in arcpy.ListFields(OutputfeatureClass)]
for field in fields:
    print(field)

 as a way of double checking the names of each of your fields post-join and making sure that the names match exactly, and also working out whether the spatial join is running as you intend it to.

0 Kudos
by Anonymous User
Not applicable

I don't think you need to calculate the field, since you are using the field map (just move it to the final output) you can rename the output fields that you want in your final output so team_name from the join could be mapped to xxx_team_Name.  Look at the env setting for using qualified field names. Changing this adds or removes the table.field style field name from the joined result. 

The field name is set to the path of OutputFeatureclass there so that may be a problem as well:

OutputFeatureClass = r"{}\incident_data\imagery\2023_UAS_photos.gdb\UASTemp".format(env)

field="{}.team_Name".format(OutputFeatureClass)

 As an example- changing the geotagging result to memory as a temp dataset:

arcpy.env.qualifiedFieldNames = False

# Geotagged Photos to Points
temp = arcpy.management.GeoTaggedPhotosToPoints(InputFolder, r'memory/geoLyr', None, "ONLY_GEOTAGGED", "ADD_ATTACHMENTS")

geotagged = arcpy.management.AddSpatialJoin(target_features=temp, join_features="https://services.arcgis.com/XG15cJAlne2vxtgt/arcgis/rest/services/UASAO_v2/FeatureServer/0",
    join_operation="JOIN_ONE_TO_ONE", join_type="KEEP_ALL", match_option = "WITHIN", search_radius = None, distance_field_name = "")

# Here is where you can add more fields to be mapped to the output.
fldPair = {team_Name': 'xxx_team_name'}

fldmap = arcpy.FieldMappings()
# Creating field maps for the two files
fldmap.addTable(geotagged)

# output the fc with changed field names using the dictionary above as old: new
for field in fldmap.fields:
    if fldPair.get(field.name):
        fldmap.removeFieldMap(fldmap.findFieldMapIndex(field.name))
        ufldmap = arcpy.FieldMap()
        ufldmap.addInputField(geotagged, field.name)
        ufldmap_name = ufldmap.outputField
        ufldmap_name.name = fldPair.get(field.name)
        ufldmap_name.aliasName = fldPair.get(field.name)
        ufldmap.outputField = ufldmap_name
        fldmap.addFieldMap(ufldmap)

arcpy.FeatureClassToFeatureClass_conversion(geotagged, r'incident_data\imagery\2023_UAS_photos.gdb', 'UASTemp', '',  fldmap)

 

0 Kudos