Select to view content in your preferred language

Help selecting required assemblies

1011
4
04-23-2013 04:15 AM
EdwardDean
Emerging Contributor
Hello Everyone,

I am relatively new to python and need some help. I have a electrical dataset consisting of lines and poles. The purpose of my script is to spatially join poles that are snapped to secondary lines. Then I need to select the poles that do not contain at least one of the required assemblies, such as J, K, and UM5. The data contained in the pole's table in the Assemblies field might contain one or more assemblies separated by commas (e.g. 'C1', 'E1-1', 'F4-1', 'K11-8', 'M2-1')

# import modules
import arcpy, os, sys, traceback, datetime, time

CURDATE = time.strftime("%Y%m%d_%H%M%S")#datetime.datetime.now() #datetime.date.today()

# identify workspace

arcpy.env.workspace = "E:\\Geog4500\\Project\\Data\\Saulsbury_214-Full.mdb"

arcpy.env.overwriteOutput = True

# define variables and output path
gdbFeatureDataset = "\\DRG"
outPath = "E:\\Geog4500\\Project\\Saulsbury_214-Full.mdb\\"
outFCjoined = outPath + os.sep + gdbFeatureDataset + os.sep + "PoleLines"
outFClines = "Poles"

# define variables
fcPole = gdbFeatureDataset + os.sep + "Pole"
poleLayer = 'Pole_Layer'

fcLine = gdbFeatureDataset + os.sep + "LineFeatures"
lineLayer = 'Line_Layer'

search_Distance = '0 FEET'

# identify log file
logpath = "E:\\Geog4500\\Project\\Data\\logfiles"
logfile1 = logpath + "log_" + str(CURDATE) + ".txt"
print("Logfile Name: " + logfile1)

if arcpy.Exists(logfile1):
    arcpy.Delete_management(logfile1)
    
# Begin logging
log1 = open(logfile1, 'w')
log1.write("Spatially Join Poles to Line Sections & Identify Pole Assemblies\n")

# Start Geoprocessing
try:
    #Create Pole Feature Layer
    arcpy.MakeFeatureLayer_management(fcPole, poleLayer)
    #Display feature count of point feature layer
    countSelectedPoles = arcpy.GetCount_management(poleLayer)
    print 'The number of selected Poles is ' + str(countSelectedPoles)
    log1.write('The number of selected Poles is ' + str(countSelectedPoles) + "\n")

    #Create Line Feature Layer
    querySecondaryLines = "[Subtype] in (2,3)"
    arcpy.MakeFeatureLayer_management(fcLine, lineLayer, querySecondaryLines)
    #Display feature count of line feature layer
    countTotalLines = arcpy.GetCount_management(fcLine)
    print 'The total number of features in the LineFeatures feature class is ' + str(countTotalLines)
    log1.write('The total number of features in the LineFeatures feature class is ' + str(countTotalLines) + "\n")

    countSelectedLines = arcpy.GetCount_management(lineLayer)
    print 'The total number of selected Secondary LineFeatures is ' + str(countSelectedLines)
    log1.write('The total number of selected Secondary LineFeatures is ' + str(countSelectedLines) + "\n")

    #Select Secondary Poles (poleLayer) that INTERSECT LineFeatures
    arcpy.SelectLayerByLocation_management(poleLayer, "WITHIN_A_DISTANCE", lineLayer, "", "NEW_SELECTION")    
    #Display the number selected Secondary Poles (poleLayer) that INTERSECT LineFeatures (lineLayer)
    selectedSecondaryPoles = arcpy.GetCount_management(poleLayer)
    print 'The number of poles selected is ' + str(selectedSecondaryPoles)
    log1.write('The number of poles selected is ' + str(selectedSecondaryPoles) + "\n")

    # Create a copy of the Selected Poles to a feature class
    try:
        arcpy.CopyFeatures_management(poleLayer, gdbFeatureDataset + os.sep + "PoleLines_" + str(CURDATE))
        print("Copied Selected Poles to a feature class.")
        log1.write("Copied Selected Poles to a feature class." + "\n")
    except:
        print("Failed to copy selected poles to a feature class for later viewing.")
        log1.write("Failed to copy selected poles to a feature class for later viewing." + "\n")
   
    #if countSpatialJoin > 0:
    if selectedSecondaryPoles > 0:
        
        ##Identify Selected Poles without "J", "K", and "UM5" values in ASSEMBLIES field
        # Loop through each Selected Pole to query and identify Assumblies
        print"Loop through each Selected Pole to query and identify Assumblies"
        log1.write("Loop through each Selected Pole to query and identify Assumblies" + "\n")
        
        #Create Update Cursor to update ISSUE field if Assemblies are missing
        # Python Set (tuple) of Missing Assembly Values
        requiredAssemblies = ("J", "K", "U")  
        # Update Cursor Based on Spatial Join Output
        try:
            uRows = arcpy.UpdateCursor(poleLayer, "", "", "", "")
            update = True
            print("Update Cursor Created.")
            log1.write("Update Cursor Created." + "\n")
        except:
            update = False
            print("Update Cursor Failed to be created.")
            log1.write("Update Cursor Failed to be created." + "\n")
        
        # Start looping of rows to update
        if update:
            for row in uRows:
                # Create a value to indicate when AT LEAST ONE assembly has been found
                assemblyIssue = True
                assembliesFound = True
                # select Assemblies and split the values to create a list
                if row.ASSEMBLIES is not None:
                    print("Current row's Assemblies: ")
                    assemblies = row.ASSEMBLIES.split(",")
                    print(assemblies)
                    # Compare available Assemblies to ("J", "K", "U")
                    for assembly in assemblies:
                        if assembly in requiredAssemblies:  
                            assemblyIssue = False
                            break
                else:
                    assembliesFound = False
                    
               
                if assembliesFound == False:
                    if row.Issue == "-":
                        row.Issue = "No Assemblies Assigned to Pole"
                    elif row.Issue == "No Assemblies Assigned to Pole":
                        pass
                    else:
                        row.Issue = "No Assemblies Assigned to Pole; " + row.Issue
                    uRows.updateRow(row)
                if assemblyIssue:
                    if row.Issue == "-":
                        row.Issue = "'J', 'K', or 'UM5' were not found"
                    elif row.Issue == "'J', 'K', or 'UM5' were not found":
                        pass
                    else:
                        row.Issue = "'J', 'K', or 'UM5' were not found; " + row.Issue
                    uRows.updateRow(row)
                
                #Write information to log file
                print("ObjectID: " + str(row.OBJECTID) + " does not have a value matching 'J', 'K', or 'UM5'.")
                log1.write("ObjectID: " + str(row.OBJECTID) + " does not have a value matching 'J', 'K', or 'UM5'." + "\n")
    else:
        print("No Poles were spatially joined to the LineFeatures.")
        log1.write("No Poles were spatially joined to the LineFeatures." + "\n")
        
    print("Script Completed.")
    log1.write("Script Completed." + "\n")
    log1.close()

except:
    tb = sys.exc_info()[2]
    tbinfo = traceback.format_tb(tb)[0]
    pymsg = "PYTHON ERRORS:\nTraceback Info:\n" + tbinfo + "\nError Info:\n     " + str(sys.exc_type) + ": " + str(sys.exc_value)+ "\n"
    msgs = "ARCPY ERRORS:\n" + arcpy.GetMessages(2) + "\n"

    print("Scripted Ended with Errors")
    log1.write("Scripted Ended with Errors" + "\n")
    
    print msgs
    arcpy.AddError(msgs)
    log1.write(msgs)
    
    print pymsg
    arcpy.AddError(pymsg)
    log1.write(pymsg + "\n")
    
    print arcpy.GetMessages(1)
    arcpy.AddMessage(arcpy.GetMessages(1))
    log1.close()


Thanks in advance,
Ed
Tags (2)
0 Kudos
4 Replies
ChrisSnyder
Honored Contributor
What specific part of your code are you having trouble with? It seems that the code you provided should work, or at least seems like a decent outline for what you are trying to do.

Judging from the paths you are using in your code and the general nature of your question, I'm pretty sure this is homework of some kind, but since I know what a UM5 and C1 is (!), I'll try to help you out.
0 Kudos
EdwardDean
Emerging Contributor
What specific part of your code are you having trouble with? It seems that the code you provided should work, or at least seems like a decent outline for what you are trying to do. 

Judging from the paths you are using in your code and the general nature of your question, I'm pretty sure this is homework of some kind, but since I know what a UM5 and C1 is (!), I'll try to help you out.


Thanks for your reply and yes this a homework assignment. If this is the wrong forum for this post I apologies.

Yes the script will run but the print statements that are produced indicate no assemblies matching J, K, or UM5 exists in the current row. Then when the current row's assemblies are listed they contain assemblies matching J, k, and UM5.

For example: Print Statement
ObjectID: 24 does not have a value matching 'J', 'K', or 'UM5'.
Current row's Assemblies:
[u'J5-8', u'K11-8']

I believe my problem lies somewhere in the following code.

# Start looping of rows to update
        if update:
            for row in uRows:
                # Create a value to indicate when AT LEAST ONE assembly has been found
                assemblyIssue = True
                assembliesFound = True
                # select Assemblies and split the values to create a list
                if row.ASSEMBLIES is not None:
                    print("Current row's Assemblies: ")
                    assemblies = row.ASSEMBLIES.split(",")
                    print(assemblies)
                    # Compare available Assemblies to ("J", "K", "U")
                    for assembly in assemblies:
                        if assembly in requiredAssemblies:  
                            assemblyIssue = False
                            break
                else:
                    assembliesFound = False


I have tried assigning "J%", "K%", "U%" to requiredAssemblies variable but i receive an error.
Thanks again for your help.
0 Kudos
ChrisSnyder
Honored Contributor
Cursor-based "queries" are quite a bit different than a SQL query where you can use wildcards and what not. Try this:

Instead of:

if assembly in requiredAssemblies:

use
if requiredAssemblies in assembly:


However, this might not be a good idea since it is what they call "implicit" and not explicit.

For example:

"j" in ["j","k","l"]
>>> True

"j" in "sonja"
>>> True

I think what you really want to know is if there is a "J","K", or "U" as the 1st letter in the assembly code, correct? This would be a more explicit expectation than just wanting to know if, for example, the letter "J" occurs somewhere in the assembly code, which is what my 1st code example is doing.

How about something like:
for assembly in assemblies:
    if assembly[0] in requiredAssemblies:   
        assemblyIssue = False


The [0] indicates the 1st character (index 0) in the assembly text variable. An index of [-1] would then be the last character, and you can use "composite" indicies like this:

print "Mickey"[1:-1]
>>> icke
0 Kudos
EdwardDean
Emerging Contributor
I really appreciate your help with the issues with my script. I am still having issues looping through to see if a required assembly is present in the assemblies field. After looking at the data there are only 2 rows that do not have any of the required assemblies but the script creates a new field (issues) and populates every record in the feature class with assemblies do not have "J", "K", or "U". So I have more issues than I thought.

Thanks again for your time and help.
0 Kudos