def rand_string(resultsOutputQueue, xCount): """ Generates a random string of numbers, lower- and uppercase chars. """ rand_str = ''.join(random.choice( string.ascii_lowercase + string.ascii_uppercase + string.digits) for i in range(xCount)) countedNumber = GetCount_management('Counties_No_Z') #output.put(rand_str + str(countedNumber)) startTime = str(datetime.datetime.now()) xCount = str(xCount) randomNumber = random.randint(1, 105) searchCursorWhereClause = "\"COUNTY_NUMBER\" = " + str(randomNumber) + " " newCursor = daSearchCursor('Counties_No_Z', ["COUNTY_NAME", "COUNTY_NUMBER", "SHAPE@"], searchCursorWhereClause) for rowItem in newCursor: rowItemString = "Cursor Row Item: " + str(rowItem[0]) + " & " + str(int(rowItem[1])) + "." endTime = str(datetime.datetime.now()) resultsOutputQueue.put("Process number: " + xCount + "\n " + "Started: " + startTime + " \n " + "Ended: " + str(datetime.datetime.now()) + "\n " + rand_str + " " + str(countedNumber) + " " + str(rowItemString)) if "newCursor" in locals(): del newCursor else: pass
def rand_string(resultsOutputQueue, xCount): """ Generates a random string of numbers, lower- and uppercase chars. """ rand_str = ''.join( random.choice(string.ascii_lowercase + string.ascii_uppercase + string.digits) for i in range(xCount)) countedNumber = GetCount_management('Counties_No_Z') #output.put(rand_str + str(countedNumber)) startTime = str(datetime.datetime.now()) xCount = str(xCount) randomNumber = random.randint(1, 105) searchCursorWhereClause = "\"COUNTY_NUMBER\" = " + str(randomNumber) + " " newCursor = daSearchCursor('Counties_No_Z', ["COUNTY_NAME", "COUNTY_NUMBER", "SHAPE@"], searchCursorWhereClause) for rowItem in newCursor: rowItemString = "Cursor Row Item: " + str(rowItem[0]) + " & " + str( int(rowItem[1])) + "." endTime = str(datetime.datetime.now()) resultsOutputQueue.put("Process number: " + xCount + "\n " + "Started: " + startTime + " \n " + "Ended: " + str(datetime.datetime.now()) + "\n " + rand_str + " " + str(countedNumber) + " " + str(rowItemString)) if "newCursor" in locals(): del newCursor else: pass
def writeStewardPointCounts(): MakeFeatureLayer_management(originalPointsSource, originalPointsAsLayer) MakeFeatureLayer_management(simplifiedPointsSource, simplifiedPointsAsLayer) allStewardsDict = dict() #Programatically grab the stewards instead of manually listing them here newCursor = daSearchCursor(originalPointsAsLayer, ["OID@", "STEWARD"]) for cursorItem in newCursor: allStewardsDict[cursorItem[1]] = 'True' if 'newCursor' in locals(): try: del newCursor except: print("The cursor exists, but it could not be successfully removed.") else: print("The cursor has already been removed.") try: wHandle = open(outputFile,'w') columnNames = "StewardID , OriginalCount , SimplifiedCount\n" wHandle.write(columnNames) # For each steward in the list, get a count of all of the original centerline # points and the the simplified road centerlines points. # Next, write the data out to a text file in comma separated form. for stewardItem in allStewardsDict.keys(): if stewardItem is not None: selectionQuery = """ "STEWARD" = '""" + stewardItem + """' """ SelectLayerByAttribute_management(originalPointsAsLayer, selectionTypeToUse, selectionQuery) oCountResult = GetCount_management(originalPointsAsLayer) originalCount = int(oCountResult.getOutput(0)) SelectLayerByAttribute_management(simplifiedPointsAsLayer, selectionTypeToUse, selectionQuery) sCountResult = GetCount_management(simplifiedPointsAsLayer) simplifiedCount = int(sCountResult.getOutput(0)) strToWrite = "'" + stewardItem + "'" + ", " + str(originalCount) + ", " + str(simplifiedCount) + "\n" print("Writing " + strToWrite + " to the file: " + outputFile + ".") wHandle.write(strToWrite) else: print("The stewardItem is None, so it will be skipped.") except: errorInfo = sys.exc_info()[0] errorInfo1 = sys.exc_info()[1] print("An error occurred: " + str(errorInfo) + str(errorInfo1)) try: wHandle.close() except: raise try: del errorInfo del errorInfo1 except: pass
def getBorderFeatureList(): print "Getting border feature list." borderFeatureCursor = daSearchCursor(countyBorderFeature, countyBorderFields) borderFeaturesToReturn = list() for borderFeature in borderFeatureCursor: borderFeaturesToReturn.append(borderFeature) # Just return the borderFeature... have other operations get the countyBorderFeatureCentroid # and countyBorderFeatureArea as needed. return borderFeaturesToReturn
def writeAggregateTableToKanDrive(): try: #truncating CDRS segments in KanDrive Spatial print str(datetime.datetime.now()) + " truncating RCRS segments in KanDrive Spatial." TruncateTable_management(kanDriveSpatialConditions) featuresToTransfer = list() # searchCursorFields go to r"in_memory\RCRS". (Input table)(Indirect) descObject = Describe(r"in_memory\RCRS") searchCursorFields = [field.name for field in descObject.fields if field.name != descObject.OIDFieldName and field.name != "Shape" and field.name != "ID1"] searchCursorFields.append('SHAPE@') RCRS_SearchCursor = daSearchCursor(aggregateTable, searchCursorFields) for RCRS_CursorItem in RCRS_SearchCursor: featureItem = list(RCRS_CursorItem) featuresToTransfer.append(featureItem) # Make the insertCursor use the same fields as the searchCursor. insertCursorFields = searchCursorFields RCRS_InsertCursor = daInsertCursor(kanDriveSpatialConditions, insertCursorFields) for RCRS_Feature in featuresToTransfer: insertOID = RCRS_InsertCursor.insertRow(RCRS_Feature) print "Inserted a row with the OID of: " + str(insertOID) except: print "An error occurred." errorItem = sys.exc_info()[1] errorStatement = str(errorItem.args[0]) print errorStatement if len(errorStatement) > 253: errorStatement = errorStatement[0:253] else: pass endTime = datetime.datetime.now() ScriptStatusLogging('KanDrive_Spatial_Conditions_Update', 'kandrive_spatial.DBO.Conditions', scriptFailure, startTime, endTime, errorItem.args[0], pythonLogTable) try: del errorItem except: pass
def getRoadLinesList(): print "Getting the road lines list." # Need a new function here. -- Instead of calling this twice, have a main-style funtion # call it once and then pass it as an argument to both functions. roadCursor = daSearchCursor(countyRoadsFeature, roadCursorFields) # @UndefinedVariable roadLinesToReturn = list() for roadPolyline in roadCursor: roadLinesToReturn.append(list(roadPolyline)) if "roadCursor" in locals(): del roadCursor else: pass return roadLinesToReturn
def manageLogLength(): logTableDesc = Describe(pythonLogTable) logLengthCheckCursor = daSearchCursor(pythonLogTable, logTableDesc.OIDFieldName) shouldTruncate = False for logItem in logLengthCheckCursor: if int(logItem[0]) > 5000: shouldTruncate = True else: pass if shouldTruncate == True: print "Log table size is too big." print "Truncating log table." TruncateTable_management(pythonLogTable) else: pass
def getBorderFeatureList(quarterOrHalf): if quarterOrHalf.lower() == "quarter": countyBorderFeature = countyBorderFeature_Q elif quarterOrHalf.lower() == "half": countyBorderFeature = countyBorderFeature_H else: print "quarterOrHalf variable not correctly defined." raise (Exception("quarterOrHalf error.")) print "Getting border feature list." borderFeatureCursor = daSearchCursor(countyBorderFeature, countyBorderFields) borderFeaturesToReturn = list() for borderFeature in borderFeatureCursor: borderFeaturesToReturn.append(borderFeature) return borderFeaturesToReturn
def reportExtensionForCSIP(csipGDBWithOutput): # Create a blank line before the CSIP error counts. try: with open(errorReportCSV, 'a') as fHandle: fHandle.write('\n') except: print("There was an error writing to the file.") csipGDBWithOutputFrequencyTable = os.path.join( csipGDBWithOutput, "SelfIntersectingRoutes_CategoryCounts") if Exists(csipGDBWithOutputFrequencyTable): csipCursorFields = ["SelfIntersectionType", "FREQUENCY"] newCursor = daSearchCursor(csipGDBWithOutputFrequencyTable, csipCursorFields) errorDescriptionAndCountDict = dict() for cursorItem in newCursor: if cursorItem[0] is not None and cursorItem[1] is not None: errorDescriptionAndCountDict[cursorItem[0]] = cursorItem[1] else: print("Either the cursorItem[0] or cursorItem[1] were none.") print( "Will not add this cursorItem to the csip output dictionary." ) # To get the listed error descriptions with associated counts, in order. for errorDescToRecordFirst in csip_ordered_report_rows: errorDescription = errorDescToRecordFirst errorCount = errorDescriptionAndCountDict.get( errorDescToRecordFirst, None) if errorCount is not None: print("There were " + str(errorCount) + " errors features with the description of: \t" + str(errorDescription) + ".") try: with open(errorReportCSV, 'a') as fHandle: fHandle.write(errorDescription + ', ' + str(errorCount) + '\n') except: print("There was an error writing to the file.") else: print("There were 0 errors with the description of: \t" + str(errorDescription) + ".") try: with open(errorReportCSV, 'a') as fHandle: fHandle.write(errorDescription + ', ' + '0' + '\n') except: print("There was an error writing to the file.") complexSelfIntersectionsCount = 0 # To get the unlisted error descriptions with associated counts, in no particular order. for errorDescription in errorDescriptionAndCountDict.keys(): if errorDescription not in csip_ordered_report_rows: if errorDescription.find( 'Complex') >= 0: # Returns -1 if not found. errorCount = errorDescriptionAndCountDict[errorDescription] complexSelfIntersectionsCount += int(errorCount) elif errorDescription == 'Not self-intersecting': pass else: # This is an issue. Print a warning. print("Warning: The error description of '" + str(errorDescription) + "'") print( "is neither in the csip_ordered_report_rows list, nor is it a Complex Self-Intersection." ) else: pass # This should have already been recorded. try: with open(errorReportCSV, 'a') as fHandle: fHandle.write('Complex Self-Intersection' + ', ' + str(complexSelfIntersectionsCount) + '\n') except: print("There was an error writing to the file.") else: print("Could not find the Output Frequency Table in the csip GDB.")
def featureReplacement(sourceFL, targetFL, featuresToSelect): # 1c.) Get the common fields so that you can search and insert correctly. targetFeatureDesc = Describe(targetFL) targetFeatureFields = targetFeatureDesc.fields targetFeatureOIDField = targetFeatureDesc.OIDFieldName targetFeatureShapeField = targetFeatureDesc.shapeFieldName targetFeatureFieldNames = [x.name for x in targetFeatureFields] sourceFeatureDesc = Describe(sourceFL) sourceFeatureFields = sourceFeatureDesc.fields sourceFeatureOIDField = sourceFeatureDesc.OIDFieldName sourceFeatureShapeField = sourceFeatureDesc.shapeFieldName sourceFeatureFieldNames = [x.name for x in sourceFeatureFields] excludeFieldNames = [targetFeatureOIDField, targetFeatureShapeField, sourceFeatureOIDField, sourceFeatureShapeField] searchCursorFields = [x for x in targetFeatureFieldNames if x in sourceFeatureFieldNames and x not in excludeFieldNames] searchCursorFields.append('SHAPE@') # Remove and then re-add the uniqueKeyField so that it is the last column and can be easily referenced. searchCursorFields.remove(str(uniqueKeyFieldToUse)) searchCursorFields.append(str(uniqueKeyFieldToUse)) insertCursorFields = searchCursorFields # Select the features in the source layer SelectLayerByAttribute_management(sourceFL, "NEW_SELECTION", featuresToSelect) # Repeat the selection in the target layer SelectLayerByAttribute_management(targetFL, "NEW_SELECTION", featuresToSelect) # Then select the common segments spatially, with some room for possible movement. SelectLayerByLocation_management(targetFL, 'WITHIN_A_DISTANCE', sourceFL, 50, 'SUBSET_SELECTION') # 5.) Count selected features in the target and delete them if there is at least 1. countResult0 = GetCount_management(targetFL) intCount0 = int(countResult0.getOutput(0)) if intCount0 >= 1: # 12.) Delete the selected features in the input layer, if any. try: DeleteFeatures_management(targetFL) except: print("Could not delete features for the selection " + str(featuresToSelect) + ".") else: pass # 10.) Count to make sure that at least one feature is selected. countResult1 = GetCount_management(sourceFL) intCount1 = int(countResult1.getOutput(0)) if intCount1 >= 1: # If so, cursor the features out featureList = list() newCursor = daSearchCursor(sourceFL, searchCursorFields) for cursorItem in newCursor: featureList.append(list(cursorItem)) try: del newCursor except: pass # 11.) Insert the selected source features into the copy of the centerlines. newCursor = daInsertCursor(targetFL, insertCursorFields) for featureItem in featureList: newCursor.insertRow(featureItem) try: del newCursor except: pass try: del featureList except: pass
def importCommentsToChangedSource(sourceWithComments, targetToHaveCommentsAdded): # Since I forgot to ask that the ReviewUser and ReviewInfo fields be kept, need to get the # data back. Thankfully, it appears to still be in the same objectID order, so we can # use that and the GCIDs to try to transfer it over, then make additional quality checks # to be sure that the transfer was successful and did not introduce any errors. # 0.) Add the ReviewUser and ReviewInfo fields to the copy if they do not already exist. # That way, the information from the edits can flow through to future edit sessions # and error checks. tfcDesc = Describe(targetToHaveCommentsAdded) tfcFields = tfcDesc.fields tfcFieldNames = [x.name for x in tfcFields] try: del tfcDesc except: pass # Check for ReviewUser field in the targetFeaturesCopy, then add it if missing. if 'ReviewUser' not in tfcFieldNames: #ReviewUser (String, 50) AddField_management(targetToHaveCommentsAdded, 'ReviewUser', "TEXT", "", "", 50, 'ReviewUser', nullable) else: pass # Check for ReviewInfo field in the targetFeaturesCopy, then add it if missing. if 'ReviewInfo' not in tfcFieldNames: #ReviewInfo (String, 250) AddField_management(targetToHaveCommentsAdded, 'ReviewInfo', "TEXT", "", "", 250, 'ReviewInfo', nullable) else: pass tfcUpdatedDesc = Describe(targetToHaveCommentsAdded) tfcUpdatedFields = tfcUpdatedDesc.fields tfcUpdatedOIDFieldName = tfcUpdatedDesc.OIDFieldName tfcUpdatedFieldNames = [x.name for x in tfcUpdatedFields] try: del tfcUpdatedDesc except: pass try: tfcUpdatedFieldNames.remove(tfcUpdatedOIDFieldName) except: pass try: tfcUpdatedFieldNames.remove(GCIDFieldName) except: pass tfcUpdatedFieldNames.append(tfcUpdatedOIDFieldName) tfcUpdatedFieldNames.append(GCIDFieldName) swcDesc = Describe(sourceWithComments) swcFields = swcDesc.fields swcOIDFieldName = swcDesc.OIDFieldName swcFieldNames = [x.name for x in swcFields] try: del swcDesc except: pass try: swcFieldNames.remove(swcOIDFieldName) except: pass try: swcFieldNames.remove(GCIDFieldName) except: pass swcFieldNames.append(swcOIDFieldName) # Add the OIDFieldName so that it is the 2nd to last swcFieldNames.append(GCIDFieldName) # Add 'GCID' so that it is the last sharedFieldNames = [x for x in tfcUpdatedFieldNames if x in swcFieldNames] # 1.) Use a searchCursor to pull the sourceWithComments features, including the OID and their GCID. withCommentsList = list() newCursor = daSearchCursor(sourceWithComments, sharedFieldNames) for cursorRow in newCursor: withCommentsList.append(cursorRow) try: del newCursor except: pass print("The sharedFieldNames are: " + str(sharedFieldNames) + ".") # 2.) Use an updateCursor to match the pulled rows and update the target rows with the ReviewUser and ReviewInfo. newCursor = daUpdateCursor(targetToHaveCommentsAdded, sharedFieldNames) for cursorRow in newCursor: for commentedRowItem in withCommentsList: if cursorRow[-1] == commentedRowItem[-1] and cursorRow[-2] == commentedRowItem[-2]: print ('Updating a row with GCID: ' + str(cursorRow[-1]) + ' and OID: ' + str(cursorRow[-2]) + '.') newCursor.updateRow(commentedRowItem) try: del newCursor except: pass
def createUniqueIdentifier(): '''filters through records and calculates an incremental Unique Identifier for routes that are not border routes, to handle Y's, eyebrows, and splits that would cause complex routes''' workspaceLocation = gdb #MakeFeatureLayer_management(lyr,"RCL_Particles",where_clause="COUNTY_L = COUNTY_R AND STATE_L = STATE_R AND ( L_F_ADD =0 OR L_T_ADD =0 OR R_F_ADD =0 OR R_T_ADD =0)") featureClassName = lyr #from arcpy.da import SearchCursor as daSearchCursor, UpdateCursor as daUpdateCursor, Editor as daEditor alphabetListForConversion = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] newCursor = daSearchCursor(featureClassName, uniqueIdInFields) searchList = list() for searchRow in newCursor: searchList.append(list(searchRow)) # Transforms the row tuple into a list so it can be edited. if "newCursor" in locals(): del newCursor else: pass matchCount = 0 matchList = list() for testRow in searchList: if (testRow[1] == testRow[2] and testRow[3] == testRow[4] and (str(testRow[5]) == "0" or str(testRow[6]) == "0" or str(testRow[7]) == "0" or str(testRow[8]) == "0")): matchCount += 1 matchList.append(testRow) matchedRowDictionary = dict() for matchedRow in matchList: matchedRowContainer = list() # If the key already exists, assign the previous list of lists # to the list container, then append the new list # before updating the new value to that key in the dictionary. if matchedRow[10] in matchedRowDictionary: matchedRowContainer = matchedRowDictionary[matchedRow[10]] matchedRowContainer.append(matchedRow) matchedRowDictionary[matchedRow[10]] = matchedRowContainer # Otherwise, the key needs to be created # with the value, the list container, having only # one list contained within it for now. else: matchedRowContainer.append(matchedRow) matchedRowDictionary[matchedRow[10]] = matchedRowContainer for LRSKey in matchedRowDictionary: outRowContainer = matchedRowDictionary[LRSKey] # Sort based on length outRowContainer = sorted(outRowContainer, key = lambda sortingRow: sortingRow[11]) countVariable = 0 # Start at 0 for unique values LRSVariable = "" for outRowIndex, outRow in enumerate(outRowContainer): # Is this the first list/row in the key's list container? # If so, then set the Resolution_Order to 0 if outRowIndex == 0: outRow[9] = 0 else: countVariable += 1 if countVariable in [1, 2, 3, 4, 5, 6, 7, 8, 9]: outRow[9] = countVariable elif countVariable >= 10 and countVariable <= 34: outRow[9] = alphabetListForConversion[countVariable - 10] # Converts countVariable to an alpha character, without the letter "O". else: print "The count Variable is above 34. Ran out of numbers and letters to use as unique values." LRSVariable = outRow[10] LRSVariableShortened = str(LRSVariable[:-1]) # Returns the LRSVariable without the last character. LRSVariable = LRSVariableShortened + str(outRow[9]) outRow[10] = LRSVariable outRowString = "" for outRowElement in outRow: outRowString = outRowString + str(outRowElement) + " " print outRowString outRowContainer[outRowIndex] = outRow matchedRowDictionary[LRSKey] = outRowContainer newEditingSession = daEditor(workspaceLocation) newEditingSession.startEditing() newEditingSession.startOperation() newCursor = daUpdateCursor(featureClassName, uniqueIdOutFields) # @UndefinedVariable for existingRow in newCursor: formattedOutRow = list() if existingRow[2] in matchedRowDictionary.keys(): outRowContainer = matchedRowDictionary[existingRow[2]] for outRow in outRowContainer: if existingRow[0] == outRow[0]: # Test for matching OBJECTID fields. formattedOutRow.append(outRow[0]) formattedOutRow.append(outRow[9]) formattedOutRow.append(outRow[10]) newCursor.updateRow(formattedOutRow) else: pass else: pass newEditingSession.stopOperation() newEditingSession.stopEditing(True) if "newCursor" in locals(): del newCursor else: pass
def TnA(): try: env.workspace = stagews #copying oracle tables to memory print str(datetime.datetime.now()) + ' copying oracle tables to memory' FeatureClassToFeatureClass_conversion(sdeCDRS,"in_memory","Construction","#","ALERT_STATUS <> 3") MakeQueryTable_management(sdeCDRSWZ,"wz1","USE_KEY_FIELDS","KANROAD.CDRS_WZ_DETAIL.CDRS_WZ_DETAIL_ID", """KANROAD.CDRS_WZ_DETAIL.CDRS_WZ_DETAIL_ID #;KANROAD.CDRS_WZ_DETAIL.CDRS_DETOUR_TYPE_ID #; KANROAD.CDRS_WZ_DETAIL.WORK_ZONE_DESC #;KANROAD.CDRS_WZ_DETAIL.WORK_ZONE_SPEED_RESTRIC #; KANROAD.CDRS_WZ_DETAIL.DETOUR_TYPE_TXT #;KANROAD.CDRS_WZ_DETAIL.DETOUR_SPEED_RESTRIC #; KANROAD.CDRS_WZ_DETAIL.DETOUR_DESC #""", "#") TableToTable_conversion("wz1", 'in_memory', 'wz') #Joining the Oracle CDRS WZ table print str(datetime.datetime.now()) + " Joining the Oracle CDRS WZ table" MakeFeatureLayer_management("Construction", "ConstJoin") AddJoin_management("ConstJoin","CDRS_WZ_DETAIL_ID","wz","KANROAD_CDRS_WZ_DETAIL_CDRS_WZ_DETAIL_ID","KEEP_ALL") FeatureClassToFeatureClass_conversion("ConstJoin","in_memory","CDRS","#",'ConstJoin.ALERT_STATUS < 3', "#") #reformatting the Route name for US routes print str(datetime.datetime.now()) + " reformatting the Route name for US routes" AddField_management("CDRS", "RouteName", "TEXT", "#", "10") routenamed = '!Construction_BEG_LRS_ROUTE![0:1] +str(!Construction_BEG_LRS_ROUTE![3:6]).lstrip("0")' # calculation expression #Calculate the Route names for User Display print routenamed CalculateField_management("CDRS", "RouteName", routenamed, "PYTHON_9.3","#") AddField_management("CDRS", "STATUS", "TEXT", "#", "10") AddField_management("CDRS", "Alert_Status_I", "LONG", "#", "#") CalculateField_management("CDRS", "Alert_Status_I", '!Construction_ALERT_STATUS!' , "PYTHON_9.3", "#") #Assigning projection for KanRoad CDRS Alert Route Layer print str(datetime.datetime.now()) + " Assigning projection for KanRoad CDRS Alert Route Layer" DefineProjection_management("CDRS", lambertCC) #reformatting the Route name for US routes print str(datetime.datetime.now()) + " reformatting the Route name for US routes" MakeFeatureLayer_management("CDRS", "ACTIVERoutes", '"Construction_ALERT_STATUS" = 2' ) CalculateField_management("ACTIVERoutes","STATUS",'"Active"',"PYTHON_9.3","#") MakeFeatureLayer_management("CDRS", "ClosedRoutes", '"Construction_ALERT_STATUS" = 2 AND "Construction_FEA_CLOSED" = 1') CalculateField_management("ClosedRoutes","STATUS",'"Closed"',"PYTHON_9.3","#") MakeFeatureLayer_management("CDRS", "PlannedRoutes", '"Construction_ALERT_STATUS" = 1' ) CalculateField_management("PlannedRoutes","STATUS",'"Planned"',"PYTHON_9.3","#") #copying joined oracle tables to memory for loading in Wichway Schema print str(datetime.datetime.now()) + " copying joined oracle tables to memory for loading in Wichway Schema" FeatureClassToFeatureClass_conversion(sdeKandriveConstruction, "in_memory", "CDRS_Segments", "#", "#") #delete rows in the destination feature class DeleteRows_management("CDRS_Segments") ############################################################################################################### # Maintainability information: # If you need to add another field to transfer between the two, just add it to the searchCursorFields and the # insertCursorFields lists and make sure that it is in the same position in the list order for both of # them. # Besides 'LoadDate', the order does not matter, so long as each field name in the # searchCursorFields has a counterpart in the insertCursorFields and vice versa. # 'LoadDate' should always be last for the insertCursorFields as it is appended to each row after all # of the other items from the searchCursorFields. ############################################################################################################### featuresToTransfer = list() # searchCursorFields go to "in_memory\CDRS". (Input table) searchCursorFields = ['SHAPE@', 'RouteName', 'Construction_BEG_STATE_LOGMILE', 'Construction_END_STATE_LOGMILE', 'Construction_BEG_COUNTY_NAME', 'Construction_ALERT_DATE', 'Construction_COMP_DATE', 'Construction_ALERT_TYPE_TXT', 'Construction_ALERT_DESC_TXT', 'Construction_VERT_RESTRICTION', 'Construction_WIDTH_RESTRICTION', 'Construction_TIME_DELAY_TXT', 'Construction_PUBLIC_COMMENT', 'wz_KANROAD_CDRS_WZ_DETAIL_DETOUR_TYPE_TXT', 'wz_KANROAD_CDRS_WZ_DETAIL_DETOUR_DESC', 'Construction_CONTACT_NAME', 'Construction_CONTACT_PHONE', 'Construction_CONTACT_EMAIL', 'Construction_ALERT_HYPERLINK', 'Alert_Status_I', 'Construction_FEA_CLOSED', 'STATUS', 'Construction_ALERT_DIREC_TXT', 'Construction_BEG_LONGITUDE', 'Construction_BEG_LATITUDE'] # insertCursorFields go to sdeKandriveConstruction. (Output table) insertCursorFields = ['SHAPE@', 'RouteName', 'BeginMP', 'EndMP', 'County', 'StartDate', 'CompDate', 'AlertType', 'AlertDescription', 'HeightLimit', 'WidthLimit', 'TimeDelay', 'Comments', 'DetourType', 'DetourDescription', 'ContactName', 'ContactPhone', 'ContactEmail', 'WebLink', 'AlertStatus', 'FeaClosed', 'Status', 'AlertDirectTxt', 'X', 'Y', 'LoadDate'] cdrsSearchCursor = daSearchCursor(r"in_memory\CDRS", searchCursorFields, """ "Alert_Status_I" <> 3""") for cdrsCursorItem in cdrsSearchCursor: featureItem = list(cdrsCursorItem) featureItem.append(starttime) featuresToTransfer.append(featureItem) ##Debug for feature in featuresToTransfer: print feature ## RemoveJoin_management("ConstJoin", "wz") #truncating CDRS segments in WICHWAY SPATIAL print str(datetime.datetime.now()) + " truncating CDRS segments in WICHWAY SPATIAL" TruncateTable_management(sdeKandriveConstruction) cdrsInsertCursor = daInsertCursor(sdeKandriveConstruction, insertCursorFields) for cdrsFeature in featuresToTransfer: insertOID = cdrsInsertCursor.insertRow(cdrsFeature) print "Inserted a row with the OID of: " + str(insertOID) except: print "An error occurred." errorItem = sys.exc_info()[1] print errorItem.args[0] try: del errorItem except: pass raise finally: try: del cdrsSearchCursor except: pass try: del cdrsInsertCursor except: pass
def createCountyLinesForEachCounty(): env.workspace = sqlGdbLocation inputCountyLines = sharedCountyLines inputCountyPolygons = sharedCounties dissolvedCountyLines = countyLinesDissolved loadedCounties = 'loadedCounties' tempCountyLines = r'in_memory\tempCountyLines' outputCountyLines = countyLinesIntersectedNoPath bufferCursorFields = ["OBJECTID"] # Dissolve all of those county lines into one set of lines # then, need to create 105 features that are are intersected # with the polygons from said line dissolve. Dissolve_management(inputCountyLines, dissolvedCountyLines) Buffer_analysis(inputCountyPolygons, countiesBuffered, "15500 Feet") bufferedCountyPolygonList = list() outputFeatureList = list() # 1st SearchCursor newCursor = daSearchCursor(countiesBuffered, bufferCursorFields) for newRow in newCursor: bufferedCountyPolygonList.append(list(newRow)) if 'newCursor' in locals(): del newCursor else: pass MakeFeatureLayer_management(countiesBuffered, loadedCounties) loadedCountiesFields = ListFields(loadedCounties) for loadedCountiesField in loadedCountiesFields: print "A loadedCountiesField was found: " + str( loadedCountiesField.name) for listedRow in bufferedCountyPolygonList: selectNumber = listedRow[0] whereClause = """ "OBJECTID" = """ + str(selectNumber) print "The whereClause = " + str(whereClause) SelectLayerByAttribute_management(loadedCounties, "NEW_SELECTION", whereClause) Intersect_analysis([dissolvedCountyLines, loadedCounties], tempCountyLines, "ALL") # 2nd SearchCursor newCursor = daSearchCursor(tempCountyLines, ["SHAPE@", "County_Number", "County_Name"]) for newRow in newCursor: outputFeatureList.append(newRow) if 'newCursor' in locals(): del newCursor else: pass try: Delete_management(countyLinesIntersectedWithUser) except: pass CreateFeatureclass_management(sqlGdbLocation, outputCountyLines, "POLYLINE", "", "", "", spatialReferenceProjection) AddField_management(outputCountyLines, "County_Number", "DOUBLE", "", "", "") AddField_management(outputCountyLines, "County_Name", "TEXT", "", "", "55") print "First Intersected County Row: " + str(outputFeatureList[0]) countyLinesIntersectFields = ["SHAPE@", "County_Number", "County_Name"] newCursor = daInsertCursor(countyLinesIntersectedPath, countyLinesIntersectFields) counter = 1 for outputFeature in outputFeatureList: rowToInsert = ([outputFeature]) insertedOID = newCursor.insertRow(outputFeature) counter += 1 print "Inserted Row with Object ID of " + str(insertedOID) if 'newCursor' in locals(): del newCursor else: pass
def transferFeatures(): env.workspace = in_memory featuresToTransfer = list() try: # Create an in_memory feature class which to hold the features from # the Oracle table. FeatureClassToFeatureClass_conversion(kanRoadRCRSRoads, "in_memory", "RCRS") # Then, define a projection on it, since the original Oracle table # is lacking the proper information. DefineProjection_management("in_memory\RCRS", lambertCC) # truncating CDRS segments in KanDrive Spatial print str(datetime.datetime.now()) + " truncating RCRS segments in KanDrive Spatial." TruncateTable_management(kanDriveSpatialConditions) ############################################################################################################### # Maintainability information: # If you need to add another field to transfer between the two, just add it to both of the # tables and give it the same name in both. ############################################################################################################### # searchCursorFields go to r"in_memory\RCRS". (Input table)(Indirect) descObject = Describe(r"in_memory\RCRS") searchCursorFields = [ field.name for field in descObject.fields if field.name != descObject.OIDFieldName and field.name != "Shape" and field.name != "ID1" ] searchCursorFields.append("SHAPE@") # Make the insertCursor use the same fields as the searchCursor. insertCursorFields = searchCursorFields print "OIDFieldname = " + descObject.OIDFieldName print "fieldNames to be used in the searchCursor (and insertCursor):" for fieldName in searchCursorFields: print fieldName RCRS_SearchCursor = daSearchCursor(r"in_memory\RCRS", searchCursorFields) for RCRS_CursorItem in RCRS_SearchCursor: featureItem = list(RCRS_CursorItem) featuresToTransfer.append(featureItem) RCRS_InsertCursor = daInsertCursor(kanDriveSpatialConditions, insertCursorFields) for RCRS_Feature in featuresToTransfer: insertOID = RCRS_InsertCursor.insertRow(RCRS_Feature) print "Inserted a row with the OID of: " + str(insertOID) except: print "An error occurred." errorItem = sys.exc_info()[1] errorStatement = str(errorItem.args[0]) print errorStatement if len(errorStatement) > 253: errorStatement = errorStatement[0:253] else: pass endTime = datetime.datetime.now() ScriptStatusLogging( "KanDrive_Spatial_Conditions_Update", "kandrive_spatial.DBO.Conditions", scriptFailure, startTime, endTime, errorStatement, pythonLogTable, ) try: del errorItem except: pass # Reraise the error to stop execution and prevent a success message # from being inserted into the table. raise finally: try: del RCRS_SearchCursor except: pass try: del RCRS_InsertCursor except: pass
def transferBasedOnLocalRouteKeys(): # Build a list of the unique route keys that match the given criteria: # Then, use that list to select the features in the source with those # keys. # Next, spatially select features in the target layer with the # selected features from the source layer. # If there are more than 0 features selected, delete the selected # target features. # Then, cursor in the selected source features. subsetSelectionQuery = """ KDOT_LRS_KEY LIKE '%L%' AND NOT KDOT_LRS_KEY LIKE '%W%' """ fcAsFeatureLayerForTransferring = 'FCAsFeatureLayer_Transferring' if Exists(fcAsFeatureLayerForTransferring): Delete_management(fcAsFeatureLayerForTransferring) else: pass MakeFeatureLayer_management(fcWithroutesToTransferFrom, fcAsFeatureLayerForTransferring) MakeFeatureLayer_management(targetFC1, targetFC1asFeatureLayer) lrsKeyFieldList = [str(lrsKeyToUse)] newCursor = daSearchCursor(fcWithroutesToTransferFrom, lrsKeyFieldList, subsetSelectionQuery) uniqueLRSKeysDict = dict() for cursorRow in newCursor: uniqueLRSKeysDict[str(cursorRow[0])] = 1 try: del newCursor except: pass uniqueLRSKeysList = uniqueLRSKeysDict.keys() try: uniqueLRSKeysList.remove('None') except: print( "Could not remove 'None' from the list of uniqueLRSKeys since it was not a part of the list." ) print("LRSKey list creation successful.") print('Found ' + str(len(uniqueLRSKeysList)) + ' unique LRS Keys in the centerline data for this query:') print(str(subsetSelectionQuery)) #Use multiSelection multiSelectionQueryBase = str( str(subsetSelectionQuery) + ''' AND ''' + ''' "''' + str(lrsKeyToUse) + '''" IS NOT NULL AND "''' + str(lrsKeyToUse) + '''" IN (''') multiSelectionQuery = multiSelectionQueryBase multiCounter = 0 ##multiDissolveFields = [str(lrsKeyToUse), 'LRS_COUNTY_PRE', 'LRS_ROUTE_PREFIX', 'LRS_ROUTE_NUM', 'LRS_ROUTE_SUFFIX', 'LRS_UNIQUE_IDENT', ## 'LRS_UNIQUE_IDENT1', 'KDOT_COUNTY_L', 'KDOT_COUNTY_R'] ##multiDissolveFields = str(lrsKeyToUse) + ';LRS_COUNTY_PRE;LRS_ROUTE_PREFIX;LRS_ROUTE_NUM;LRS_ROUTE_SUFFIX;LRS_UNIQUE_IDENT;LRS_UNIQUE_IDENT1' ##multiStatsFields = str(n1FromMeas) + " MIN;" + str(n1ToMeas) + " MAX" ##multiStatsFields = "" ##singlePart = "SINGLE_PART" ##unsplitLines = "UNSPLIT_LINES" # 3.) Loop through the list of unique LRS Keys for uniqueKeyItem in uniqueLRSKeysList: # Make a selection list that includes 50 keys, then select the keys and dissolve to make a new # feature class. # After the selection is dissolved, use a spatial select on the original feature class and # an attribute selection on the original feature class to see which original features should # be deleted. # Then, delete the selected features (if at least 1 selected). # Basically, doing it piece by piece is a problem since I'm not including LRS KEY # selections to prevent the spatial selection from deleting pieces that overlap, but # that should have different LRS Keys. Need to do all of the features # at once to make sure that I'm not deleting pieces that should actually be there. # Seems like it shouldn't be a problem, but the numbers say it is. # 4.) For groups of 200000 LRS Keys, select all the features with those LRS Keys. if multiCounter <= 199999: multiSelectionQuery += """'""" + str( uniqueKeyItem) + """'""" + """, """ multiCounter += 1 else: # Add the current item, then multiSelectionQuery += """'""" + str( uniqueKeyItem) + """'""" + """, """ # Remove the trailing ", " and add a closing parenthesis. multiSelectionQuery = multiSelectionQuery[:-2] + """) """ SelectLayerByAttribute_management(fcAsFeatureLayerForTransferring, "NEW_SELECTION", multiSelectionQuery) # Have to do from step 5 on here also. ### -shouldbeafunctionblock#1- ### # 5.) Count selected features. countResult0 = GetCount_management(fcAsFeatureLayerForTransferring) intCount0 = int(countResult0.getOutput(0)) if intCount0 >= 1: print( "Spatially selecting with the fcAsFeatureLayerForTransferring features, of which there are " + str(intCount0) + " selected.") ##print("Selected by this query:") ##print(str(multiSelectionQuery)) # 9.) Else, spatially select features in the original feature class with 'SHARE_A_LINE_SEGMENT_WITH'. SelectLayerByLocation_management( targetFC1asFeatureLayer, "SHARE_A_LINE_SEGMENT_WITH", fcAsFeatureLayerForTransferring, 0, "NEW_SELECTION") # Added to prevent the Selection from taking over '%W%' routes at this time. SelectLayerByAttribute_management(targetFC1asFeatureLayer, "SUBSET_SELECTION", subsetSelectionQuery) # 10.) Count to make sure that at least one feature is selected. countResult2 = GetCount_management(targetFC1asFeatureLayer) intCount2 = int(countResult2.getOutput(0)) print( 'There were ' + str(intCount2) + ' features selected for replacement in the targetFC1asFeatureLayer layer.' ) if intCount2 >= 1: # 11.) If so, cursor the features out of the dissolve layer. featureList = list() searchCursorFields = [ str(lrsKeyToUse), str(startMeasure), str(endMeasure), 'LRS_COUNTY_PRE', 'LRS_ROUTE_PREFIX', 'LRS_ROUTE_NUM', 'LRS_ROUTE_SUFFIX', 'LRS_UNIQUE_IDENT', 'LRS_UNIQUE_IDENT1', 'KDOT_COUNTY_L', 'KDOT_COUNTY_R', 'LABEL', 'SHAPE@' ] newCursor = daSearchCursor(fcAsFeatureLayerForTransferring, searchCursorFields) for cursorItem in newCursor: featureList.append(list(cursorItem)) try: del newCursor except: pass # 12.) Delete the selected features in the input layer. try: DeleteFeatures_management(targetFC1asFeatureLayer) except: print("Could not delete features for the selection " + str(multiSelectionQuery) + ".") # 13.) Insert the features from the dissolve layer into the copy of the centerlines. insertCursorFields = [ str(lrsKeyToUse), str(startMeasure), str(endMeasure), 'LRS_COUNTY_PRE', 'LRS_ROUTE_PREFIX', 'LRS_ROUTE_NUM', 'LRS_ROUTE_SUFFIX', 'LRS_UNIQUE_IDENT', 'LRS_UNIQUE_IDENT1', 'KDOT_COUNTY_L', 'KDOT_COUNTY_R', 'LABEL', 'SHAPE@' ] newCursor = daInsertCursor(targetFC1asFeatureLayer, insertCursorFields) for featureItem in featureList: newCursor.insertRow(featureItem) try: del newCursor except: pass try: del featureList except: pass else: pass ### -shouldbeafunctionblock#1- ### multiSelectionQuery = ''' "''' + str( lrsKeyToUse) + '''" IS NOT NULL AND "''' + str( lrsKeyToUse) + '''" IN (''' multiCounter = 0 # After the for loop, if there is still anything remaining which was unselected in the # the previous multiSelectionQuery steps. # Remove the trailing ", " and add a closing parenthesis. if multiSelectionQuery != multiSelectionQueryBase: multiSelectionQuery = multiSelectionQuery[:-2] + """) """ else: # The selection query would not select anything. return SelectLayerByAttribute_management(fcAsFeatureLayerForTransferring, "NEW_SELECTION", multiSelectionQuery) # Then redo from step 5 on at the end of the loop IF there is anything left to select # which was not selected... so if selectionCounter != 0. ### -shouldbeafunctionblock#2- ### # 5.) Count selected features. countResult0 = GetCount_management(fcAsFeatureLayerForTransferring) intCount0 = int(countResult0.getOutput(0)) if intCount0 >= 1: print( "Spatially selecting with the fcAsFeatureLayerForTransferring features, of which there are " + str(intCount0) + " selected.") ##print("Selected by this query:") ##print(str(multiSelectionQuery)) # 9.) Else, spatially select features in the original feature class with 'SHARE_A_LINE_SEGMENT_WITH'. SelectLayerByLocation_management(targetFC1asFeatureLayer, "SHARE_A_LINE_SEGMENT_WITH", fcAsFeatureLayerForTransferring, 0, "NEW_SELECTION") # Added to prevent the Selection from taking over '%W%' routes at this time. SelectLayerByAttribute_management(targetFC1asFeatureLayer, "SUBSET_SELECTION", subsetSelectionQuery) # 10.) Count to make sure that at least one feature is selected. countResult2 = GetCount_management(targetFC1asFeatureLayer) intCount2 = int(countResult2.getOutput(0)) print( 'There were ' + str(intCount2) + ' features selected for replacement in the targetFC1asFeatureLayer layer.' ) if intCount2 >= 1: # 11.) If so, cursor the features out of the dissolve layer. featureList = list() searchCursorFields = [ str(lrsKeyToUse), str(startMeasure), str(endMeasure), 'LRS_COUNTY_PRE', 'LRS_ROUTE_PREFIX', 'LRS_ROUTE_NUM', 'LRS_ROUTE_SUFFIX', 'LRS_UNIQUE_IDENT', 'LRS_UNIQUE_IDENT1', 'KDOT_COUNTY_L', 'KDOT_COUNTY_R', 'LABEL', 'SHAPE@' ] newCursor = daSearchCursor(fcAsFeatureLayerForTransferring, searchCursorFields) for cursorItem in newCursor: featureList.append(list(cursorItem)) try: del newCursor except: pass # 12.) Delete the selected features in the input layer. try: DeleteFeatures_management(targetFC1asFeatureLayer) except: print("Could not delete features for the selection " + str(multiSelectionQuery) + ".") # 13.) Insert the features from the dissolve layer into the copy of the centerlines. insertCursorFields = [ str(lrsKeyToUse), str(startMeasure), str(endMeasure), 'LRS_COUNTY_PRE', 'LRS_ROUTE_PREFIX', 'LRS_ROUTE_NUM', 'LRS_ROUTE_SUFFIX', 'LRS_UNIQUE_IDENT', 'LRS_UNIQUE_IDENT1', 'KDOT_COUNTY_L', 'KDOT_COUNTY_R', 'LABEL', 'SHAPE@' ] newCursor = daInsertCursor(targetFC1asFeatureLayer, insertCursorFields) for featureItem in featureList: newCursor.insertRow(featureItem) try: del newCursor except: pass try: del featureList except: pass else: pass
def dissolveBasedOnLocalRouteKeys(routesToDissolve, subsetSelectionQuery): # Moved out the selection building code to the other function where # it makes more sense. # Use similar code here to what is found in the main dissolve loop. # Just need to do multiselection on all of the possible routes that # match the subsetSelectionQuery and for each multiselection, create # a dissolve feature set, then use the same reintroduction tests # that are used in the main dissolve to reintroduce the dissolved # lines without removing any that weren't dissolved or adding # any new overlaps. fcAsFeatureLayerForDissolves = 'FCAsFeatureLayer_Dissolves' if Exists(fcAsFeatureLayerForDissolves): Delete_management(fcAsFeatureLayerForDissolves) else: pass MakeFeatureLayer_management(routesToDissolve, fcAsFeatureLayerForDissolves) lrsKeyFieldList = [str(lrsKeyToUse)] newCursor = daSearchCursor(routesToDissolve, lrsKeyFieldList, subsetSelectionQuery) uniqueLRSKeysDict = dict() for cursorRow in newCursor: uniqueLRSKeysDict[str(cursorRow[0])] = 1 try: del newCursor except: pass uniqueLRSKeysList = uniqueLRSKeysDict.keys() try: uniqueLRSKeysList.remove('None') except: print( "Could not remove 'None' from the list of uniqueLRSKeys since it was not a part of the list." ) print("LRSKey list creation successful.") print('Found ' + str(len(uniqueLRSKeysList)) + ' unique LRS Keys in the centerline data for this query:') print(str(subsetSelectionQuery)) #Use multiSelection multiSelectionQueryBase = str( str(subsetSelectionQuery) + ''' AND ''' + ''' "''' + str(lrsKeyToUse) + '''" IS NOT NULL AND "''' + str(lrsKeyToUse) + '''" IN (''') multiSelectionQuery = multiSelectionQueryBase multiCounter = 0 multiDissolveFields = [ str(lrsKeyToUse), 'LRS_COUNTY_PRE', 'LRS_ROUTE_PREFIX', 'LRS_ROUTE_NUM', 'LRS_ROUTE_SUFFIX', 'LRS_UNIQUE_IDENT', 'LRS_UNIQUE_IDENT1', 'KDOT_COUNTY_L', 'KDOT_COUNTY_R' ] ##multiDissolveFields = str(lrsKeyToUse) + ';LRS_COUNTY_PRE;LRS_ROUTE_PREFIX;LRS_ROUTE_NUM;LRS_ROUTE_SUFFIX;LRS_UNIQUE_IDENT;LRS_UNIQUE_IDENT1' ##multiStatsFields = str(n1FromMeas) + " MIN;" + str(n1ToMeas) + " MAX" multiStatsFields = "" singlePart = "SINGLE_PART" unsplitLines = "UNSPLIT_LINES" # 3.) Loop through the list of unique LRS Keys for uniqueKeyItem in uniqueLRSKeysList: # Make a selection list that includes 50 keys, then select the keys and dissolve to make a new # feature class. # After the selection is dissolved, use a spatial select on the original feature class and # an attribute selection on the original feature class to see which original features should # be deleted. # Then, delete the selected features (if at least 1 selected). # try: Delete_management(dissolveOutFC) except: print("Could not delete the dissolveOutFC layer.") # 4.) For groups of 2000 LRS Keys, select all the features with those LRS Keys. if multiCounter <= 1999: multiSelectionQuery += """'""" + str( uniqueKeyItem) + """'""" + """, """ multiCounter += 1 else: # Add the current item, then multiSelectionQuery += """'""" + str( uniqueKeyItem) + """'""" + """, """ # Remove the trailing ", " and add a closing parenthesis. multiSelectionQuery = multiSelectionQuery[:-2] + """) """ SelectLayerByAttribute_management(fcAsFeatureLayerForDissolves, "NEW_SELECTION", multiSelectionQuery) # Have to do from step 5 on here also. ### -shouldbeafunctionblock#1- ### # 5.) Count selected features. countResult0 = GetCount_management(fcAsFeatureLayerForDissolves) intCount0 = int(countResult0.getOutput(0)) if intCount0 >= 1: # 6.) Make a new layer or dissolved layer from this selection. Dissolve_management(fcAsFeatureLayerForDissolves, dissolveOutFC, multiDissolveFields, multiStatsFields, singlePart, unsplitLines) # 7.) Count the number of dissolved features. countResult1 = GetCount_management(dissolveOutFC) intCount1 = int(countResult1.getOutput(0)) print('Counted ' + str(intCount1) + ' features returned for that dissolve.') # 8a.) If the number of dissolved features is 0, then append the error to the error file # and go on to the next LRS Key in the loop. if intCount1 == 0: with open(dissolveErrorsFile, 'a') as errorFile: errorFile.write(str(multiSelectionQuery)) # 8b.) From the spatial select, select the subset of features that also have a matching LRS Key. else: SelectLayerByAttribute_management( fcAsFeatureLayerForDissolves, 'NEW_SELECTION', multiSelectionQuery) # 9.) Else, spatially select features in the original feature class with 'SHARE_A_LINE_SEGMENT_WITH'. SelectLayerByLocation_management( fcAsFeatureLayerForDissolves, 'SHARE_A_LINE_SEGMENT_WITH', dissolveOutFC, 0, 'SUBSET_SELECTION') # 10.) Count to make sure that at least one feature is selected. countResult2 = GetCount_management( fcAsFeatureLayerForDissolves) intCount2 = int(countResult2.getOutput(0)) print( 'There were ' + str(intCount2) + ' features selected for replacement in the fcAsFeatureLayerForDissolves layer.' ) if intCount2 >= 1: # 11.) If so, cursor the features out of the dissolve layer. featureList = list() searchCursorFields = [ str(lrsKeyToUse), 'LRS_COUNTY_PRE', 'LRS_ROUTE_PREFIX', 'LRS_ROUTE_NUM', 'LRS_ROUTE_SUFFIX', 'LRS_UNIQUE_IDENT', 'LRS_UNIQUE_IDENT1', 'KDOT_COUNTY_L', 'KDOT_COUNTY_R', 'SHAPE@' ] newCursor = daSearchCursor(dissolveOutFC, searchCursorFields) for cursorItem in newCursor: featureList.append(list(cursorItem)) try: del newCursor except: pass # 12.) Delete the selected features in the input layer. try: DeleteFeatures_management( fcAsFeatureLayerForDissolves) except: print( "Could not delete features for the selection " + str(multiSelectionQuery) + ".") # 13.) Insert the features from the dissolve layer into the copy of the centerlines. insertCursorFields = [ str(lrsKeyToUse), 'LRS_COUNTY_PRE', 'LRS_ROUTE_PREFIX', 'LRS_ROUTE_NUM', 'LRS_ROUTE_SUFFIX', 'LRS_UNIQUE_IDENT', 'LRS_UNIQUE_IDENT1', 'KDOT_COUNTY_L', 'KDOT_COUNTY_R', 'SHAPE@' ] newCursor = daInsertCursor( fcAsFeatureLayerForDissolves, insertCursorFields) for featureItem in featureList: newCursor.insertRow(featureItem) try: del newCursor except: pass try: del featureList except: pass else: pass multiSelectionQuery = ''' "''' + str( lrsKeyToUse) + '''" IS NOT NULL AND "''' + str( lrsKeyToUse) + '''" IN (''' multiCounter = 0 ### -shouldbeafunctionblock#1- ### # After the for loop, if there is still anything remaining which was unselected in the # the previous multiSelectionQuery steps. # Remove the trailing ", " and add a closing parenthesis. if multiSelectionQuery != multiSelectionQueryBase: multiSelectionQuery = multiSelectionQuery[:-2] + """) """ else: # The selection query would not select anything. return SelectLayerByAttribute_management(fcAsFeatureLayerForDissolves, "NEW_SELECTION", multiSelectionQuery) # Then redo from step 5 on at the end of the loop IF there is anything left to select # which was not selected... so if selectionCounter != 0. ### -shouldbeafunctionblock#2- ### # 5.) Count selected features. countResult0 = GetCount_management(fcAsFeatureLayerForDissolves) intCount0 = int(countResult0.getOutput(0)) if intCount0 >= 1: # 6.) Make a new layer or dissolved layer from this selection. -- Question about fields. Dissolve_management(fcAsFeatureLayerForDissolves, dissolveOutFC, multiDissolveFields, multiStatsFields, singlePart, unsplitLines) # 7.) Count the number of dissolved features. countResult1 = GetCount_management(dissolveOutFC) intCount1 = int(countResult1.getOutput(0)) print('Counted ' + str(intCount1) + ' features returned for that dissolve.') # 8a.) If the number of dissolved features is 0, then append the error to the error file # and go on to the next LRS Key in the loop. if intCount1 == 0: with open(dissolveErrorsFile, 'a') as errorFile: errorFile.write(str(multiSelectionQuery)) # 8b.) From the spatial select, select the subset of features that also have a matching LRS Key. else: SelectLayerByAttribute_management(fcAsFeatureLayerForDissolves, 'NEW_SELECTION', multiSelectionQuery) # 9.) Else, spatially select features in the original feature class with 'SHARE_A_LINE_SEGMENT_WITH'. SelectLayerByLocation_management(fcAsFeatureLayerForDissolves, 'SHARE_A_LINE_SEGMENT_WITH', dissolveOutFC, 0, 'SUBSET_SELECTION') # 10.) Count to make sure that at least one feature is selected. countResult2 = GetCount_management(fcAsFeatureLayerForDissolves) intCount2 = int(countResult2.getOutput(0)) print( 'There were ' + str(intCount2) + ' features selected in the fcAsFeatureLayerForDissolves layer.' ) if intCount2 >= 1: # 11.) If so, cursor the features out of the dissolve layer. featureList = list() searchCursorFields = [ str(lrsKeyToUse), 'LRS_COUNTY_PRE', 'LRS_ROUTE_PREFIX', 'LRS_ROUTE_NUM', 'LRS_ROUTE_SUFFIX', 'LRS_UNIQUE_IDENT', 'LRS_UNIQUE_IDENT1', 'KDOT_COUNTY_L', 'KDOT_COUNTY_R', 'SHAPE@' ] newCursor = daSearchCursor(dissolveOutFC, searchCursorFields) for cursorItem in newCursor: featureList.append(list(cursorItem)) try: del newCursor except: pass # 12.) Delete the selected features in the input layer. try: DeleteFeatures_management(fcAsFeatureLayerForDissolves) except: print("Could not delete features for the selection " + str(multiSelectionQuery) + ".") # 13.) Insert the features from the dissolve layer into the copy of the centerlines. insertCursorFields = [ str(lrsKeyToUse), 'LRS_COUNTY_PRE', 'LRS_ROUTE_PREFIX', 'LRS_ROUTE_NUM', 'LRS_ROUTE_SUFFIX', 'LRS_UNIQUE_IDENT', 'LRS_UNIQUE_IDENT1', 'KDOT_COUNTY_L', 'KDOT_COUNTY_R', 'SHAPE@' ] newCursor = daInsertCursor(fcAsFeatureLayerForDissolves, insertCursorFields) for featureItem in featureList: newCursor.insertRow(featureItem) try: del newCursor except: pass try: del featureList except: pass else: pass
def main(): # Do this by county. # Get a list of all of the available county numbers. # Then create an updateCursor for each county, using # a selection that looks at the LRS_COUNTY_PRE and LRS_PREFIX or existing KDOT_LRS_KEY. tempDesc = Describe(fcWithLocalRoutesToDissolveAndMeasure) print( "Updating the concatenated LRS Key Field and start/end measures for selected features in " + returnFeatureClass(tempDesc.catalogPath) + ".") OIDFieldName = str(tempDesc.OIDFieldName) try: del tempDesc except: pass uniqueCountyCodeDict = dict() countyCodeFieldsList = ['KDOT_COUNTY_L', 'KDOT_COUNTY_R'] newCursor = daSearchCursor(fcWithLocalRoutesToDissolveAndMeasure, countyCodeFieldsList) for cursorRow in newCursor: uniqueCountyCodeDict[str(cursorRow[0])] = 1 uniqueCountyCodeDict[str(cursorRow[1])] = 1 try: del newCursor except: pass uniqueCountyCodeList = list() for uniqueCountyCode in uniqueCountyCodeDict.keys(): uniqueCountyCodeList.append(uniqueCountyCode) try: del uniqueCountyCodeDict except: pass try: uniqueCountyCodeList.remove('None') except: pass sortedUniqueCountyCodes = sorted( uniqueCountyCodeList ) # No need to specify a key since it's one column. for uniqueCountyCodeItem in sortedUniqueCountyCodes: print('Selecting features based on countyCode: ' + str(uniqueCountyCodeItem) + '.') routeFeaturesList = list() listOfFieldsToUse = [ OIDFieldName, 'LRS_COUNTY_PRE', 'LRS_ROUTE_PREFIX', 'LRS_ROUTE_NUM', 'LRS_ROUTE_SUFFIX', 'LRS_UNIQUE_IDENT', 'LRS_UNIQUE_IDENT1', lrsKeyToUse ] # Modified from the original localroutenumbering sql to include an exception for '%W%' routes, because I don't think that those # were included in the localroutenumbering, even though they should have been. selectionQuery1 = """ KDOT_COUNTY_L = '""" + str( uniqueCountyCodeItem ) + """' AND (((KDOT_LRS_KEY IS NULL AND LRS_ROUTE_PREFIX = 'L') OR KDOT_LRS_KEY LIKE '%L%') AND NOT KDOT_LRS_KEY LIKE '%W%') """ selectionQuery2 = """ KDOT_COUNTY_L IS NULL AND KDOT_COUNTY_R = '""" + str( uniqueCountyCodeItem ) + """' AND (((KDOT_LRS_KEY IS NULL AND LRS_ROUTE_PREFIX = 'L') OR KDOT_LRS_KEY LIKE '%L%') AND NOT KDOT_LRS_KEY LIKE '%W%') """ newCursor = daUpdateCursor(fcWithLocalRoutesToDissolveAndMeasure, listOfFieldsToUse, selectionQuery1) for cursorRow in newCursor: cursorListItem = list(cursorRow) # change each cursorRow to a list # then pass the list to a function that concats the parts # into the LRS key field. concattedKeyListItem = concatTheLRSParts(cursorListItem, uniqueCountyCodeItem) # Receive the list back and use it to update the # row. newCursor.updateRow(concattedKeyListItem) try: del newCursor except: pass newCursor = daUpdateCursor(fcWithLocalRoutesToDissolveAndMeasure, listOfFieldsToUse, selectionQuery2) for cursorRow in newCursor: cursorListItem = list(cursorRow) # change each cursorRow to a list # then pass the list to a function that concats the parts # into the LRS key field. concattedKeyListItem = concatTheLRSParts(cursorListItem, uniqueCountyCodeItem) # Receive the list back and use it to update the # row. newCursor.updateRow(concattedKeyListItem) try: del newCursor except: pass # At this point, all of the local features in a county should have had # their LRS keys updated. # What we need to do now is to dissolve them based on LRS key. dissolveBasedOnLocalRouteKeys(fcWithLocalRoutesToDissolveAndMeasure, selectionQuery1) dissolveBasedOnLocalRouteKeys(fcWithLocalRoutesToDissolveAndMeasure, selectionQuery2) # At this point, all of the local featuers should be dissolved into # single part lines. # Go ahead and add the measures based on 0-to-shapelength. calculateMeasuresForLocalRoutes(fcWithLocalRoutesToDissolveAndMeasure, selectionQuery1) calculateMeasuresForLocalRoutes(fcWithLocalRoutesToDissolveAndMeasure, selectionQuery2)
def transferFeatures(): env.workspace = in_memory featuresToTransfer = list() try: # Create an in_memory feature class which to hold the features from # the Oracle table. FeatureClassToFeatureClass_conversion(sdeCMLRS,"in_memory","CMLRS") #truncating CDRS segments in KanDrive Spatial print str(datetime.datetime.now()) + " truncating CMLRS segments in KanDrive Spatial." env.workspace = gdbCMLRSLocation TruncateTable_management(gdbCMLRSTable) env.workspace = in_memory ############################################################################################################### # Maintainability information: # If you need to add another field to transfer between the two, just add it to both of the # tables and give it the same name in both. ############################################################################################################### # searchCursorFields go to r"in_memory\CMLRS". (Input table)(Indirect) Sde_CMLRS_Object = Describe(r"in_memory\CMLRS") Sde_CMLRS_Fields = [field.name for field in Sde_CMLRS_Object.fields] Gdb_CMLRS_Object = Describe(gdb_93_CMLRS) Gdb_CMLRS_Fields = [field.name for field in Gdb_CMLRS_Object.fields] # This Python list comprehension creates the intersection of the two *_Fields lists # and makes sure that the Shape field and Object ID fields are not directly # transfered. -- The 'SHAPE@' token indirectly transfers the geometry instead # and the Object ID of the target feature class is automatically calculated # by the insert cursor. searchCursorFields = [fieldName for fieldName in Sde_CMLRS_Fields if fieldName in Gdb_CMLRS_Fields and fieldName != Sde_CMLRS_Object.OIDFieldName and fieldName != Gdb_CMLRS_Object.OIDFieldName and fieldName != 'Shape'] searchCursorFields.append('SHAPE@') # Make the insertCursor use the same fields as the searchCursor. insertCursorFields = searchCursorFields print "fieldNames to be used in the searchCursor (and insertCursor):" for fieldName in searchCursorFields: print fieldName CMLRS_SearchCursor = daSearchCursor(r"in_memory\CMLRS", searchCursorFields) for CMLRS_CursorItem in CMLRS_SearchCursor: featureItem = list(CMLRS_CursorItem) featuresToTransfer.append(featureItem) CMLRS_InsertCursor = daInsertCursor(gdb_93_CMLRS, insertCursorFields) for CMLRS_Feature in featuresToTransfer: insertOID = CMLRS_InsertCursor.insertRow(CMLRS_Feature) print "Inserted a row with the OID of: " + str(insertOID) except: print "An error occurred." errorItem = sys.exc_info()[1] errorStatement = str(errorItem.args[0]) print errorStatement if len(errorStatement) > 253: errorStatement = errorStatement[0:253] else: pass endTime = datetime.datetime.now() ScriptStatusLogging('Cansys_CMLRS_Transfer', 'SharedSDEProd.gdb\SHARED_CANSYS_CMLRS', scriptFailure, startTime, endTime, errorStatement, pythonLogTable) try: del errorItem except: pass # Reraise the error to stop execution and prevent a success message # from being inserted into the table. raise finally: try: del CMLRS_SearchCursor except: pass try: del CMLRS_InsertCursor except: pass
def createUniqueIdentifier(): '''filters through records and calculates an incremental Unique Identifier for routes that are not border routes, to handle Y's, eyebrows, and splits that would cause complex routes''' workspaceLocation = gdb #MakeFeatureLayer_management(lyr,"RCL_Particles",where_clause="COUNTY_L = COUNTY_R AND STATE_L = STATE_R AND ( L_F_ADD =0 OR L_T_ADD =0 OR R_F_ADD =0 OR R_T_ADD =0)") featureClassName = lyr #from arcpy.da import SearchCursor as daSearchCursor, UpdateCursor as daUpdateCursor, Editor as daEditor alphabetListForConversion = [ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" ] newCursor = daSearchCursor(featureClassName, uniqueIdInFields) searchList = list() for searchRow in newCursor: searchList.append( list(searchRow) ) # Transforms the row tuple into a list so it can be edited. if "newCursor" in locals(): del newCursor else: pass matchCount = 0 matchList = list() for testRow in searchList: if (testRow[1] == testRow[2] and testRow[3] == testRow[4] and (str(testRow[5]) == "0" or str(testRow[6]) == "0" or str(testRow[7]) == "0" or str(testRow[8]) == "0")): matchCount += 1 matchList.append(testRow) matchedRowDictionary = dict() for matchedRow in matchList: matchedRowContainer = list() # If the key already exists, assign the previous list of lists # to the list container, then append the new list # before updating the new value to that key in the dictionary. if matchedRow[10] in matchedRowDictionary: matchedRowContainer = matchedRowDictionary[matchedRow[10]] matchedRowContainer.append(matchedRow) matchedRowDictionary[matchedRow[10]] = matchedRowContainer # Otherwise, the key needs to be created # with the value, the list container, having only # one list contained within it for now. else: matchedRowContainer.append(matchedRow) matchedRowDictionary[matchedRow[10]] = matchedRowContainer for LRSKey in matchedRowDictionary: outRowContainer = matchedRowDictionary[LRSKey] # Sort based on length outRowContainer = sorted(outRowContainer, key=lambda sortingRow: sortingRow[11]) countVariable = 0 # Start at 0 for unique values LRSVariable = "" for outRowIndex, outRow in enumerate(outRowContainer): # Is this the first list/row in the key's list container? # If so, then set the Resolution_Order to 0 if outRowIndex == 0: outRow[9] = 0 else: countVariable += 1 if countVariable in [1, 2, 3, 4, 5, 6, 7, 8, 9]: outRow[9] = countVariable elif countVariable >= 10 and countVariable <= 34: outRow[9] = alphabetListForConversion[ countVariable - 10] # Converts countVariable to an alpha character, without the letter "O". else: print "The count Variable is above 34. Ran out of numbers and letters to use as unique values." LRSVariable = outRow[10] LRSVariableShortened = str( LRSVariable[:-1] ) # Returns the LRSVariable without the last character. LRSVariable = LRSVariableShortened + str(outRow[9]) outRow[10] = LRSVariable outRowString = "" for outRowElement in outRow: outRowString = outRowString + str(outRowElement) + " " print outRowString outRowContainer[outRowIndex] = outRow matchedRowDictionary[LRSKey] = outRowContainer newEditingSession = daEditor(workspaceLocation) newEditingSession.startEditing() newEditingSession.startOperation() newCursor = daUpdateCursor(featureClassName, uniqueIdOutFields) # @UndefinedVariable for existingRow in newCursor: formattedOutRow = list() if existingRow[2] in matchedRowDictionary.keys(): outRowContainer = matchedRowDictionary[existingRow[2]] for outRow in outRowContainer: if existingRow[0] == outRow[ 0]: # Test for matching OBJECTID fields. formattedOutRow.append(outRow[0]) formattedOutRow.append(outRow[9]) formattedOutRow.append(outRow[10]) newCursor.updateRow(formattedOutRow) else: pass else: pass newEditingSession.stopOperation() newEditingSession.stopEditing(True) if "newCursor" in locals(): del newCursor else: pass
def RoadinName(roadFeatures, nameExclusions): """This module corrects the road names in the soundex code where the road is named like Road A or Road 12 """ # Need to add logic to remove the ST from roads like 3RD ST and make sure that this translates to 0003 # and not 003. fieldList = ['OBJECTID', 'RD', 'Soundex'] #Placeholder. Recompiled in nameExclusions for loop. listMatchString = re.compile(r'^WEST', re.IGNORECASE) roadNameString = '' roadPreSoundexString = '' roadSoundexString = '' holderList = list() testMatch0 = None testMatch1 = None testMatch2 = None testMatch3 = None # Get the data from the geodatabase so that it can be used in the next part of the function. cursor = daSearchCursor(roadFeatures, fieldList) # @UndefinedVariable for row in cursor: listRow = list(row) holderList.append(listRow) # Clean up if "cursor" in locals(): del cursor else: pass if "row" in locals(): del row else: pass # Matches any group of 3 alpha characters in the string, ignoring case. tripleAlphaMatchString = re.compile(r'[A-Z][A-Z][A-Z]', re.IGNORECASE) # Matches 1 or 2 alpha characters at the start of a string, ignoring case. singleOrDoubleAlphaMatchString = re.compile(r'^[A-Z]$|^[A-Z][A-Z]$', re.IGNORECASE) # Matches 1 to 4 digits at the start of a string, probably no reason to ignore case in the check. singleToQuadNumberMatchString = re.compile( r'^[0-9]$|^[0-9][0-9]$|^[0-9][0-9][0-9]$|^[0-9][0-9][0-9][0-9]$') anyNumberMatchString = re.compile(r'[0-9]', re.IGNORECASE) # For roads that don't match a name exclusion: singleOrDoubleNumberThenAlphaMatchString = re.compile( r'^[0-9][0-9][A-Z]$|^[0-9][A-Z]$', re.IGNORECASE) # For roads that don't match a name exclusion and should be normally Numdexed. firstCharacterNumberString = re.compile(r'^[0-9]') ## Significant structure change here 2014-11-05. ## Watch for possible bugs. ## ## Added Numdex logic to this part, which ## caused some issues. ## ## Flattened the loops out here so that it only ## does a run through the ## <for heldRow in holderList> ## loop once instead of doing it once per ## entry in the nameExclusions list via ## <for excludedText in nameExclusions> ## ## Runs faster now. After changing the regex string ## to be dynamically generated prior to compilation ## and using \b{0}\b as part of the pattern, ## errors *seem* to be gone. stringToCompile = "" # Perform some regex on the strings to produce a new soundex in certain cases. for i, excludedText in enumerate(nameExclusions): #shift left start excludedText = str(excludedText) excludedText = excludedText.upper() #listMatchString = re.compile(r'^{0}\s'.format(re.escape(excludedText)), re.IGNORECASE) ## Old version, pre-dynamic generation. if i == 0: stringToCompile = r'^\b{0}\b\ '.format(re.escape(excludedText)) else: stringToCompile = stringToCompile + r'|^\b{0}\b\ '.format( re.escape(excludedText)) print i listMatchString = re.compile(stringToCompile, re.IGNORECASE) print "stringToCompile = " + str(stringToCompile) for heldRow in holderList: roadNameString = '' roadPreSoundexString = '' roadSoundexString = '' roadNameString = str(heldRow[1]) roadNameString = roadNameString.upper() roadNameString = roadNameString.replace(".", "") exclusionMatch = listMatchString.search(roadNameString) if exclusionMatch != None: # Testing for excluded Road Names such as "Road" and "CR" in "Road 25" and "CR 2500". # Get the characters from the end of the testMatch to the end of the string. # Should return a string that starts with a space. roadPreSoundexString = roadNameString[exclusionMatch.end():] # Replace with a search for " " by group in regex. roadPreSoundexString = roadPreSoundexString.replace(" ", "") roadPreSoundexString = roadPreSoundexString.replace(" ", "") # then loop through the groups to replace with "" so that any number # of spaces can be removed. print "roadNameString = " + str(roadNameString) print "roadPreSoundexString = " + str(roadPreSoundexString) # Do subbing for #ST, #ND, #RD, #TH etc... for numberEnding in ordinalNumberEndings: nonsensitiveReplace = re.compile(r'[0-9]{0}'.format( re.escape(numberEnding), re.IGNORECASE)) replaceMatch = nonsensitiveReplace.search(roadNameString) if replaceMatch != None: roadPreSoundexString = re.sub(replaceMatch.group(0), "", roadPreSoundexString) else: pass # Replace with regex string that matches spaces as groups, then loop through groups to replace. roadPreSoundexString = roadPreSoundexString.replace(" ", "") roadPreSoundexString = roadPreSoundexString.replace(" ", "") testMatch0 = None testMatch0 = tripleAlphaMatchString.search(roadPreSoundexString) testMatch1 = None testMatch1 = singleOrDoubleAlphaMatchString.search( roadPreSoundexString) testMatch2 = None testMatch2 = singleToQuadNumberMatchString.search( roadPreSoundexString) testMatch3 = None testMatch3 = anyNumberMatchString.search(roadPreSoundexString) if testMatch0 != None: roadSoundexString = soundex(roadPreSoundexString) # Slice the roadSoundexString to remove the first character, but keep the rest. if len(roadSoundexString) >= 4: roadSoundexString = roadSoundexString[1:4] # The next line looks complicated, but exclusionMatch.group(0)[0:1] # is actually just getting the first letter of the first matched pattern. roadSoundexString = exclusionMatch.group( 0)[0:1] + roadSoundexString elif len(roadSoundexString) == 3: roadSoundexString = exclusionMatch.group( 0)[0:1] + roadSoundexString elif len(roadSoundexString) == 2 or len( roadSoundexString) == 1: roadSoundexString = roadSoundexString.zfill(3) roadSoundexString = exclusionMatch.group( 0)[0:1] + roadSoundexString else: pass heldRow[2] = roadSoundexString elif testMatch1 != None: # Road A, Road BB, or similar. roadPreSoundexString = roadPreSoundexString[testMatch1.start( ):testMatch1.end()] if len(roadPreSoundexString) > 2: pass elif len(roadPreSoundexString) == 2: roadSoundexString = "0" + roadPreSoundexString roadSoundexString = exclusionMatch.group( 0)[0:1] + roadSoundexString heldRow[2] = roadSoundexString elif len(roadPreSoundexString) == 1: roadSoundexString = "00" + roadPreSoundexString roadSoundexString = exclusionMatch.group( 0)[0:1] + roadSoundexString heldRow[2] = roadSoundexString else: pass elif testMatch2 != None: roadPreSoundexString = roadPreSoundexString[testMatch2.start( ):testMatch2.end()] if len(roadPreSoundexString) > 4: pass elif len(roadPreSoundexString) == 4: # Slice the string to include only the first 3 characters, as slice end is non-inclusive. roadSoundexString = roadPreSoundexString[:4] roadSoundexString = exclusionMatch.group( 0)[0:1] + roadSoundexString heldRow[2] = roadSoundexString elif len(roadPreSoundexString) == 3: roadSoundexString = roadPreSoundexString roadSoundexString = exclusionMatch.group( 0)[0:1] + roadSoundexString heldRow[2] = roadSoundexString elif len(roadPreSoundexString) == 2: roadSoundexString = "0" + roadPreSoundexString roadSoundexString = exclusionMatch.group( 0)[0:1] + roadSoundexString heldRow[2] = roadSoundexString elif len(roadPreSoundexString) == 1: roadSoundexString = "00" + roadPreSoundexString roadSoundexString = exclusionMatch.group( 0)[0:1] + roadSoundexString heldRow[2] = roadSoundexString else: pass else: pass else: roadNameString = heldRow[1] testMatch4 = None testMatch4 = singleOrDoubleNumberThenAlphaMatchString.search( roadNameString) testMatch5 = None testMatch5 = firstCharacterNumberString.search(roadNameString) # Numdex with one or two numbers, then alpha. if testMatch4 != None: roadPreSoundexString = roadNameString[testMatch4.start():] roadSoundexString = roadPreSoundexString.zfill(4) heldRow[2] = roadSoundexString # Normal Numdex if there were not one or two numbers, then alpha, but the string starts with a number. elif testMatch5 != None: numerical_re = re.compile("[A-Z]|[^0-9][^0-9][^0-9][^0-9]") roadPreSoundexString = roadNameString.replace(" ", "") roadSoundexString = re.sub(numerical_re, "", roadPreSoundexString.zfill(4)) if len(roadSoundexString) > 4: roadSoundexString = roadSoundexString[:5] else: pass roadSoundexString = roadSoundexString.zfill(4) heldRow[2] = roadSoundexString else: # Check for AA, BB, EE, etc without an excluded name in front of it if len(roadNameString) == 2: if roadNameString[0] == roadNameString[1]: roadPreSoundexString = roadNameString roadSoundexString = roadPreSoundexString.zfill(4) else: # Normal Soundex roadPreSoundexString = roadNameString roadSoundexString = soundex(roadPreSoundexString) heldRow[2] = roadSoundexString # shift left end try: # Start an edit session for this workspace because the centerline # feature class participates in a topology. editSession = daEditor(gdb) editSession.startEditing(False, False) editSession.startOperation() print "Editing started." cursor = daUpdateCursor(roadFeatures, fieldList) # @UndefinedVariable for row in cursor: for heldRow in holderList: # N^2 looping, try not to place print statements inside this block. if str(row[0]) == str(heldRow[0]): cursor.updateRow(heldRow) else: pass editSession.stopOperation() editSession.stopEditing(True) print "Editing complete." except Exception as e: print "Failed to update the Soundex values." print e.message print GetMessages(2) finally: # Clean up if "cursor" in locals(): del cursor else: pass if "row" in locals(): del row else: pass
def Kdot_RouteNameCalc(): AliasTablePath = os.path.join(gdb, Alias) cursorFields = ["OBJECTID", "A_RD", "KDOT_ROUTENAME"] sCursor = daSearchCursor(AliasTablePath, cursorFields) searchDict = dict() print "In Kdot_RouteNameCalc..." for foundRow in sCursor: searchDict[foundRow[0]] = list(foundRow) # Transforms the row tuple into a list so it can be edited. print str(foundRow[0]) + "\t" + str(foundRow[1]) try: del sCursor except: pass # Matches an I, U, or K at the start of the string, ignoring case. IUKMatchString = re.compile(r'^[IUK]', re.IGNORECASE) # Matches 1 to 3 digits at the end of a string, probably no reason to ignore case in the check. singleToTripleNumberEndMatchString = re.compile(r'[0-9][0-9][0-9]|[0-9][0-9]|[0-9]') # Probably need to use regular expressions here. # Yes, rebuild with regex. Too many problems just trying to slice the strings. for keyName in searchDict: firstPart = "" secondPart = "" fullRouteName = "" listItem = searchDict[keyName] listItemRD = listItem[1] testResult0 = None testResult1 = None #################################################################################### testResult0 = re.search(IUKMatchString, listItemRD) testResult1 = re.search(singleToTripleNumberEndMatchString, listItemRD) #################################################################################### if testResult0 is not None and testResult1 is not None: print "Found matches." firstPart = str(testResult0.group(0)) secondPart = str(testResult1.group(0)) # Pad the string with prepended zeroes if it is not 3 digits long already. if len(secondPart) == 2: secondPart = secondPart.zfill(3) print "secondPart = " + secondPart elif len(secondPart) == 1: secondPart = secondPart.zfill(3) print "secondPart = " + secondPart else: pass fullRouteName = firstPart + secondPart listItem[2] = fullRouteName searchDict[keyName] = listItem print "Resulting RouteName = " + str(listItem[2]) + "." else: print "Did not find matches." fullRouteName = firstPart + secondPart listItem[2] = fullRouteName searchDict[keyName] = listItem uCursor = daUpdateCursor(AliasTablePath, cursorFields) for uCursorItem in uCursor: for keyName in searchDict: listItem = searchDict[keyName] if uCursorItem[0] == listItem[0]: print "ObjectIDs matched: " + str(uCursorItem[0]) + " & " + str(listItem[0]) print "The road name (for updateCursor) is: " + str(listItem[1]) uCursor.updateRow(listItem) if listItem[2] is not None and listItem[2] != "": print "The routeNameFull is: " + str(listItem[2]) else: print "RouteNameFull is None/Null/Empty. =(" else: pass try: del uCursor except: pass
def exportErrorsToFeatureClasses(reviewTable, originGDB, errorOutputGDB, errorOutputGDBFolder): # Checking to see if the output already exists. # If so, remove it. if Exists(errorOutputGDB): Delete_management(errorOutputGDB) else: pass CreateFileGDB_management(errorOutputGDBFolder, returnGDBOrSDEName(errorOutputGDB)) previousWorkspace = env.workspace env.workspace = errorOutputGDB tableFields = ['ORIGINTABLE', 'CHECKTITLE', 'OBJECTID'] newCursor = daSearchCursor(reviewTable, tableFields) revRows = list() for rowItem in newCursor: revRows.append(list(rowItem)) try: del newCursor except: pass originTableList = list() checkTitleList = list() for revRowItem in revRows: originTableList.append(revRowItem[0]) checkTitleList.append(revRowItem[1]) print('Creating sets from the originTable and checkTitle lists.') originTableSet = set(originTableList) checkTitleSet = set(checkTitleList) print('Finished set creation.') originTableList = list(originTableSet) checkTitleList = list(checkTitleSet) tableAndCheckDataObjects = list() csvDictOfErrorFeatures = dict() for originTableItem in originTableList: print('Origin table = ' + originTableItem + '.') completeOriginTablePath = os.path.join(originGDB, originTableItem) print('The full path to the origin table is ' + str(completeOriginTablePath) + '.') tableViewName = "ReviewTable_View_" + str(originTableItem) originTableWhereClause = """"ORIGINTABLE" = '""" + str( originTableItem) + """'""" try: Delete_management(tableViewName) except: pass MakeTableView_management(reviewTable, tableViewName, originTableWhereClause) for checkTitleItem in checkTitleList: print('Check title = ' + checkTitleItem + '.') selectionWhereClause = """"CHECKTITLE" = '""" + str( checkTitleItem) + """'""" SelectLayerByAttribute_management(tableViewName, "NEW_SELECTION", selectionWhereClause) countResult = GetCount_management(tableViewName) intCount = int(countResult.getOutput(0)) if intCount >= 1: tempTableAndCheckData = tableAndCheckData( originTableItem, checkTitleItem) tableViewFields = ["RECORDID", "OBJECTID"] newCursor = daSearchCursor(tableViewName, tableViewFields, selectionWhereClause) newOIDList = list() for cursorItem in newCursor: newOIDList.append(cursorItem[1]) try: del newCursor except: pass tempTableAndCheckData.listOfOIDsToUse = newOIDList tableAndCheckDataObjects.append(tempTableAndCheckData) else: print("There were no features selected for the " + tableViewName + " table.") print("There are " + str(len(tableAndCheckDataObjects)) + " different items in the tableAndCheckDataObjects list.") for listObject in tableAndCheckDataObjects: featureLayerForErrorOutput = 'FeatureClassAsFeatureLayer' if Exists(featureLayerForErrorOutput): Delete_management(featureLayerForErrorOutput) else: pass fullPathToFeatureClass = os.path.join(originTablesGDB, listObject.tableName) MakeFeatureLayer_management(fullPathToFeatureClass, featureLayerForErrorOutput) # build the selection list & select up to but not more than 999 features at at time OIDTotalCounter = 0 errorOutputWhereClause = """ "OBJECTID" IN (""" for errorOID in listObject.listOfOIDsToUse: if OIDTotalCounter <= 998: errorOutputWhereClause = errorOutputWhereClause + str( errorOID) + """, """ OIDTotalCounter += 1 else: # Remove the trailing ", " and add a closing parenthesis. errorOutputWhereClause = errorOutputWhereClause[:-2] + """) """ SelectLayerByAttribute_management(featureLayerForErrorOutput, "ADD_TO_SELECTION", errorOutputWhereClause) OIDTotalCounter = 0 errorOutputWhereClause = """ "OBJECTID" IN (""" errorOutputWhereClause = errorOutputWhereClause + str( errorOID) + """, """ # Remove the trailing ", " and add a closing parenthesis. errorOutputWhereClause = errorOutputWhereClause[:-2] + """) """ SelectLayerByAttribute_management(featureLayerForErrorOutput, "ADD_TO_SELECTION", errorOutputWhereClause) ##print "Counting..." selectedErrorsResult = GetCount_management(featureLayerForErrorOutput) selectedErrorsCount = int(selectedErrorsResult.getOutput(0)) # export the selected data with the correct tableName & checkTitle outputFeatureClassName = formatCheckTitle( listObject.checkTitle) + "ErrorsFrom_" + listObject.tableName fullPathToOutputFeatureClass = os.path.join(errorOutputGDB, outputFeatureClassName) csvDictOfErrorFeatures[outputFeatureClassName] = str( selectedErrorsCount) print( str(selectedErrorsCount) + "\t features will be written to \t" + outputFeatureClassName) if selectedErrorsCount >= 1: CopyFeatures_management(featureLayerForErrorOutput, fullPathToOutputFeatureClass) time.sleep(25) AddField_management(outputFeatureClassName, "OptionalInfo", "TEXT", "", "", 250, "ReviewingInfo", nullable) else: pass # Need to write a short CSV here that tells the number and type of errors. print('Writing error information to an error reports file called ' + str(errorReportCSVName) + '.') try: with open(errorReportCSV, 'w') as fHandle: for errorFeature in errorReportRowsOrder: if errorFeature in csvDictOfErrorFeatures: errorFeatureCount = csvDictOfErrorFeatures[errorFeature] fHandle.write( str(errorFeature) + ', ' + str(errorFeatureCount) + '\n') else: fHandle.write(str(errorFeature) + ', ' + str(0) + '\n') # Add a blank line to match previous formatting. fHandle.write('\n') except: print("There was an error writing to the file.") # Modify this so that it just checks for the existence of the roads # and highways check output, rather than relying on the config # file for whether or not this should be ran. # The config file can tell the full process whether or not # to run the R&H check, but the error report should give # details on the R&H check whether or not the config file # currently states that the R&H check should be ran again # were the full process to run. env.workspace = previousWorkspace
def labelAngleNormalization(quarterOrHalf): if quarterOrHalf.lower() == "quarter": countyBorderFeature = countyBorderFeature_Q countyRoadNameRosette = countyRoadNameRosette_Q elif quarterOrHalf.lower() == "half": countyBorderFeature = countyBorderFeature_H countyRoadNameRosette = countyRoadNameRosette_H else: print "quarterOrHalf variable not correctly defined." raise (Exception("quarterOrHalf error.")) print "Normalizing the label angle values." if "COUNTY_NAME" not in ListFields(countyRoadNameRosette): AddField_management(countyRoadNameRosette, "COUNTY_NAME", "TEXT", "", "", "55") else: pass newCursor = daSearchCursor(countyBorderFeature, countyBorderFields) countyTranslationDictionary = dict() # countyBorderItem[3] is the number, countyBorderItem[2] is the name. # -- Use for translating from county number to county name. for countyBorderItem in newCursor: if countyBorderItem[3] not in countyTranslationDictionary: countyTranslationDictionary[ countyBorderItem[3]] = countyBorderItem[2] else: pass if "newCursor" in locals(): del newCursor else: pass newCursor = daUpdateCursor(countyRoadNameRosette, countyRoadNameRosetteFields) for countyPointItem in newCursor: countyPointItem = list(countyPointItem) # Takes the remainder of the angle divided by 360. # Uses fmod due to floating point issues with the normal modulo operator in python. countyPointItem[0] = math.fmod(countyPointItem[0], 360) # countyPointItem[1] is County Name, countyPointItem[2] is County Number. if countyPointItem[0] >= 250 and countyPointItem[0] <= 290: countyPointItem[0] = 270 if countyPointItem[2] in countyTranslationDictionary: countyPointItem[1] = countyTranslationDictionary[ countyPointItem[2]] else: countyPointItem[1] = "" newCursor.updateRow(countyPointItem) elif countyPointItem[0] >= 160 and countyPointItem[0] <= 200: countyPointItem[0] = 180 if countyPointItem[2] in countyTranslationDictionary: countyPointItem[1] = countyTranslationDictionary[ countyPointItem[2]] else: countyPointItem[1] = "" newCursor.updateRow(countyPointItem) elif countyPointItem[0] >= 70 and countyPointItem[0] <= 110: countyPointItem[0] = 90 if countyPointItem[2] in countyTranslationDictionary: countyPointItem[1] = countyTranslationDictionary[ countyPointItem[2]] else: countyPointItem[1] = "" newCursor.updateRow(countyPointItem) elif (countyPointItem[0] >= 0 and countyPointItem[0] <= 20) or (countyPointItem[0] >= 340 and countyPointItem[0] <= 360): countyPointItem[0] = 0 if countyPointItem[2] in countyTranslationDictionary: countyPointItem[1] = countyTranslationDictionary[ countyPointItem[2]] else: countyPointItem[1] = "" newCursor.updateRow(countyPointItem) else: print "Deleting a row for having an angle more than 20 degrees away from a cardinal direction." newCursor.deleteRow() if "newCursor" in locals(): del newCursor else: pass print "Label angle normalization complete!" print "Done extending and intersecting road features." # Need to break this into two pieces and pass some of the inmemorylayers
def duplicateNameRemoval(quarterOrHalf): if quarterOrHalf.lower() == "quarter": countyRoadNameRosette = countyRoadNameRosette_Q elif quarterOrHalf.lower() == "half": countyRoadNameRosette = countyRoadNameRosette_H else: print "quarterOrHalf variable not correctly defined." raise (Exception("quarterOrHalf error.")) print "Starting duplicate name removal." countyRoadNameRosetteFields = ListFields(countyRoadNameRosette) print "countyRoadNameRosetteFields: " for fieldItem in countyRoadNameRosetteFields: print str(fieldItem.name) newCursor = daSearchCursor(countyRoadNameRosette, countyRoadNameRosetteFieldsObjShape) # Debug only #print "Created a new cursor..." countyNamePointList = list() for eachPoint in newCursor: countyNamePointList.append(eachPoint) try: del newCursor except: pass # Debug only #print "Completed using the new cursor." pointDeleteList = list() for pointItem in countyNamePointList: for pointToCheck in countyNamePointList: # If the points share a road name, and a county number, but not the same ObjectID... if pointItem[0] not in pointDeleteList: if pointItem[3] == pointToCheck[3] and str( pointItem[2]).upper() == str( pointToCheck[2]).upper() and (not pointItem[0] == pointToCheck[0]): # Use the distance formula to check to see if these points are within a # certain distance from one another. # If so, add the pointToCheck to the pointDeleteList. distance = 0 point1 = pointItem[1] point2 = pointToCheck[1] distance = calcPointDistance(point1, point2) # Change this to add just the objectid to the pointDeleteList # instead of the whole point row to increase the speed # of the check when the list grows to a decent size. # Distance of 10000 seems to give good results. if distance >= 0 and distance < 10000 and pointToCheck[ 0] not in pointDeleteList: pointDeleteList.append(pointToCheck[0]) else: pass else: pass else: pass newCursor = daUpdateCursor(countyRoadNameRosette, countyRoadNameRosetteFieldsObjShape) for updateableRow in newCursor: for pointToDeleteOID in pointDeleteList: if updateableRow[0] == pointToDeleteOID: print "Selected a point for " + str( updateableRow[2]) + " in " + str( updateableRow[4]) + " county to delete." newCursor.deleteRow() print "Point deleted." else: pass #updateCursor #delete pointToDelete from countyRoadNameRosette. #print a message saying that the point was deleted. try: del newCursor except: pass
def bufferCrashLocationAndIntersectWithRoads(crashObject, roadsLayer, outputIncrementInt, bufferAndIntersectSR, useParseMatchAddr): #pointToBufferXY = list(crashObject.initialShapeXY) #print("The crashObject.initialShapeXY is " + str(crashObject.initialShapeXY) + " and the pointToBufferXY is " + str(pointToBufferXY) + ".") ##pointToBufferWithoutGeometry = Point(pointToBufferXY) ##pointToBuffer = PointGeometry(pointToBufferXY, bufferAndIntersectSR) pointToBuffer = crashObject.initialShape offsetDistance = crashObject.offsetDistance # Perform layer selection here, then # intersect the buffer with the selected roads. roadNameColumns = crashObject.roadNameColumns accidentClusterTolerance = 2 print( "Attempting to buffer and offset the crashObject with a unique key of: " + str(crashObject.uniqueKey) + ".") print("Using the roadNameColumns of: " + str(roadNameColumns) + ".") singlePartOffsetFeaturesList = list() try: if offsetDistance >= 5: ## Was previously failing here due to not having the name for intermediateAccidentBuffer offsetDistanceString = str(offsetDistance) + " Feet" Buffer_analysis(pointToBuffer, intermediateAccidentBuffer, offsetDistanceString, "", "", "", "", "PLANAR") if debugOutputValue == True: # Save the buffer here. Call it bufferOutput_001 to start with, and increment from there. Get the number # from the calling script. bufferOutputLocation = bufferOutputLocationBase + "_" + str( outputIncrementInt).zfill(4) copyFCToTempLocation(intermediateAccidentBuffer, bufferOutputLocation) else: pass firstRoadName = str(crashObject.onRoad) firstRoadName = firstRoadName.upper() roadNameValues = [firstRoadName] if useParseMatchAddr == True: parsedRoadNamesList = ParseMatchAddr(crashObject.matchAddress) secondRoadName = " " try: secondRoadName = parsedRoadNamesList[0] secondRoadName = secondRoadName.upper() except: pass thirdRoadName = " " try: thirdRoadName = parsedRoadNamesList[1] thirdRoadName = thirdRoadName.upper() except: pass roadNameValues = [firstRoadName, secondRoadName, thirdRoadName] else: pass streetWhereClause = generateWhereClause(roadNameColumns, roadNameValues) print("The generated whereClause is: " + str(streetWhereClause) + ".") SelectLayerByAttribute_management(roadsLayer, "NEW_SELECTION", streetWhereClause) selectionCount = str(GetCount_management(roadsLayer)) if Exists(intermediateAccidentIntersect): try: Delete_management(intermediateAccidentIntersect) except: pass else: pass if int(selectionCount) != 0: featuresToIntersect = [roadsLayer, intermediateAccidentBuffer] Intersect_analysis(featuresToIntersect, intermediateAccidentIntersect, "ALL", accidentClusterTolerance, "POINT") time.sleep(0.25) # Wait a moment for the FC to settle. # And yes, it is ridiculous that the Intersect_analysis function would return without # its output being there and ready to use, but... *ahem*. # If it doesn't exist despite having been just created, then skip to the next record. if not (Exists(intermediateAccidentIntersect)): print("There was no output from Intersect_analysis.") crashObject.singlePartOffsetFeaturesList = None return crashObject else: pass if debugOutputValue == True: # Save the intersect FC here. Call it intersectOutput_001 to start with, and increment from there. Get the number # from the calling script. intersectOutputLocation = intersectOutputLocationBase + "_" + str( outputIncrementInt).zfill(4) copyFCToTempLocation(intermediateAccidentIntersect, intersectOutputLocation) else: pass # GetCount_management is not particularly Pythonic. countResult = GetCount_management( intermediateAccidentIntersect) if int(countResult.getOutput(0)) > 0: MultipartToSinglepart_management( intermediateAccidentIntersect, intermediateAccidentIntersectSinglePart) # Maybe add a feature class to contain all of the single part points that get generated in multipart to singlepart. singlePartsCursor = daSearchCursor( intermediateAccidentIntersectSinglePart, ['SHAPE@', 'SHAPE@XY']) for singlePartRow in singlePartsCursor: ##KDOTXYFieldsList = ['OBJECTID', 'STATUS', 'POINT_X', 'POINT_Y', 'ACCIDENT_KEY', 'ON_ROAD_KDOT_NAME', ## 'AT_ROAD_KDOT_DIRECTION', 'AT_ROAD_KDOT_DIST_FEET', 'AT_ROAD_KDOT_NAME', ## 'Match_addr'] print("The singlePartRow value is: " + str(singlePartRow) + ".") print( "The singlePartRow[1][0] and singlePartRow[1][1] values are: " + str(singlePartRow[1][0]) + " and " + str(singlePartRow[1][1]) + ".") print( "The crashObject.initialShapeXY[0] and crashObject.initialShapeXY[1] values are: " + str(crashObject.initialShapeXY[0]) + " and " + str(crashObject.initialShapeXY[1]) + ".") singlePartListItem = [ crashObject.initialShapeXY[0], crashObject.initialShapeXY[1], singlePartRow[1][0], singlePartRow[1][1], singlePartRow[0] ] #Previously used, but no longer necessary = , geocodedAccident[0]] singlePartOffsetFeaturesList.append(singlePartListItem) try: del singlePartsCursor except: pass else: print( "There were zero output features counted in the intermediateAccidentIntersect feature class." ) crashObject.singlePartOffsetFeaturesList = None return crashObject else: pass # Zero road segments selected. Will not attempt to offset. else: print( "This should have been caught by the lowOrZeroDistanceOffsetCheck function, but the accidentDistanceOffset is not >= 5." ) except: print "WARNING:" print "An error occurred which prevented the crash point with Acc_Key: " + str( crashObject.uniqueKey) print "from being buffered and/or offset properly." print(traceback.format_exc()) crashObject.singlePartOffsetFeaturesList = singlePartOffsetFeaturesList return crashObject
def duplicateCheckForMAndC(): print( "Checking for duplicate route numbers in the target route numbers for R, M, and C Routes." ) # Select the R routes. # Cursor them, and add their route number to a dict. # Then, select the M routes. # Cursor them and add their route number to a dict. # Then, select the C routes. # Cursor them and add their route number to a dict. # Create a list of free route numbers that are not in any of the 3 dicts. # Then, for each M route, if its routenumber is not in the R routes dict, # mark the M route's targetRouteNumChanged to "Kept". # Otherwise, if its routenumber is in the R routes dict, # Select the next free route number in the free route numbers list. # Remove the free route number from the free route numbers list. # Assign the free route number to the M route and mark the M route's # targetRouteNumChanged to "Changed". # Then, for each C route, if its routenumber is not in the R routes dict # and if it is also not in the M routes dict, # mark the C route's targetRouteNumChanged to "Kept". # Otherwise, if its routenumber is in the R routes dict or the M routes dict, # Select the next free route number in the free route numbers list. # Remove the free route number from the free route numbers list. # Assign the free route number to the C route and mark the C route's # targetRouteNumChanged to "Changed". rRoutesDict = dict() mRoutesDict = dict() cRoutesDict = dict() rRoutesSelectionQuery = """ SourceRouteId LIKE '___R%' OR LRS_ROUTE_PREFIX = 'R' """ mRoutesSelectionQuery = """ SourceRouteId LIKE '___M%' OR LRS_ROUTE_PREFIX = 'M' """ cRoutesSelectionQuery = """ SourceRouteId LIKE '___C%' OR LRS_ROUTE_PREFIX = 'C' """ searchCursorFields = [ sourceRouteNum, targetRouteNum, targetRouteNumChanged ] newCursor = daSearchCursor(fcToCalculateTargetKeysIn, searchCursorFields, rRoutesSelectionQuery) for cursorItem in newCursor: rRoutesDict[cursorItem[-3]] = 1 try: del newCursor except: pass newCursor = daSearchCursor(fcToCalculateTargetKeysIn, searchCursorFields, mRoutesSelectionQuery) for cursorItem in newCursor: mRoutesDict[cursorItem[-3]] = 1 try: del newCursor except: pass newCursor = daSearchCursor(fcToCalculateTargetKeysIn, searchCursorFields, cRoutesSelectionQuery) for cursorItem in newCursor: cRoutesDict[cursorItem[-3]] = 1 try: del newCursor except: pass usedRoutesList = [x for x in rRoutesDict.keys()] usedRoutesList = usedRoutesList + [y for y in mRoutesDict.keys()] usedRoutesList = usedRoutesList + [z for z in cRoutesDict.keys()] sortedUsedRoutesList = sorted(usedRoutesList) freeRoutesList = [ str(x).zfill(5) for x in xrange(12000, 64000) if str(x).zfill(5) not in sortedUsedRoutesList ] print("Used routes are as follows:") for usedRouteNumber in sortedUsedRoutesList: print("Used route number = " + str(usedRouteNumber) + ".") sortedFreeRoutesList = sorted(freeRoutesList) reverseSortedFreeRoutesList = sortedFreeRoutesList[::-1] print( "Updating lrs target numbers for M routes where they conflict with R routes." ) # Check the target lrs route numbers for M routes against the R routes. rRoutesKeys = rRoutesDict.keys() newCursor = daUpdateCursor(fcToCalculateTargetKeysIn, searchCursorFields, mRoutesSelectionQuery) for mRouteItem in newCursor: mRouteListItem = list(mRouteItem) if mRouteListItem[-2] in rRoutesKeys: mRouteListItem[-1] = 'Changed' mRouteListItem[-2] = reverseSortedFreeRoutesList.pop() mRoutesDict[mRouteListItem[-2]] = 1 newCursor.updateRow(mRouteListItem) else: pass try: del newCursor except: pass print( "Updating lrs target numbers for C routes where they conflict with R routes or M routes." ) # Check the target lrs route numbers for C routes against the R routes and the M routes. mRoutesKeys = mRoutesDict.keys() newCursor = daUpdateCursor(fcToCalculateTargetKeysIn, searchCursorFields, cRoutesSelectionQuery) for cRouteItem in newCursor: cRouteListItem = list(cRouteItem) if cRouteListItem[-2] in rRoutesKeys or cRouteListItem[ -2] in mRoutesKeys: cRouteListItem[-1] = 'Changed' cRouteListItem[-2] = reverseSortedFreeRoutesList.pop() newCursor.updateRow(cRouteListItem) else: pass try: del newCursor except: pass
def soundex(s): """ Encode a string using Soundex. Takes a string and returns its Soundex representation.""" replacementString = "" #Added a "." here, should replace correctly now. replacementDict = {"A":"1", "E":"2", "H":"3", "I":"4", "O":"5", "U":"6", "W":"7", "Y":"8", ".":""} if len(s) == 2: if s[0] == s[1]:# Only affects one very specific road name type. Kind of a narrow fix. for keyName in replacementDict: if keyName == str(s[1].upper(): replacementString = replacementDict[keyName] enc = str(str(s[0]) + replacementString).zfill(4) return enc else: pass else: pass elif len(s) == 1: enc = str(s[0]).zfill(4) return enc elif len(s) == 0: enc = str("x").zfill(4) return enc else: pass s = normalize(s) last = None enc = s[0] for c in s[1:]: if len(enc) == 4: break if charsubs[c] != last: enc += charsubs[c] last = charsubs[c] while len(enc) < 4: enc += '0' return enc def numdex(s): """this module applies soundex to named streets, and pads the numbered streets with zeros, keeping the numbering system intact""" if s[0] in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.']: # I don't think having a '.' here will do anything unless the road name is ".SomeName" since it # only checks the first character of the string. numerical_re = re.compile("[A-Z]|[^0-9][^0-9][^0-9][^0-9]") s=re.sub(numerical_re,"", s.zfill(4)) return s.zfill(4) else: return soundex(s) def StreetNetworkCheck(gdb): """removes street centerlines from the topology and creates geometric network, then checks geometric network connectivity""" from arcpy import ListDatasets, VerifyAndRepairGeometricNetworkConnectivity_management, RemoveFeatureClassFromTopology_management, CreateGeometricNetwork_management, FindDisconnectedFeaturesInGeometricNetwork_management #print topo fd = ListDatasets(gdb) print fd[0] geonet = fd[0]+"\Street_Network" #print geonet if Exists(geonet): print "Street Geometric Network Already Exists" else: RemoveFeatureClassFromTopology_management(topo, "RoadCenterline") CreateGeometricNetwork_management(fd, "Street_Network", "RoadCenterline SIMPLE_EDGE NO", "#", "#", "#", "#", "#") FindDisconnectedFeaturesInGeometricNetwork_management(fd+"/RoadCenterline", "Roads_Disconnected") StreetLogfile = reviewpath+"/KDOTReview/"+ntpath.basename(ng911)+".log" VerifyAndRepairGeometricNetworkConnectivity_management(geonet, StreetLogfile, "VERIFY_ONLY", "EXHAUSTIVE_CHECK", "0, 0, 10000000, 10000000") def ConflateKDOTrestart(gdb, DOTRoads): """Conflation restart for selecting KDOT roads to conflate to the NG911 Network""" MakeFeatureLayer_management(DOTRoads+"/KDOT_HPMS_2012","KDOT_Roads","#","#","#") MakeFeatureLayer_management(checkfile+"/RoadCenterline","RoadCenterline","#","#","#") SelectLayerByLocation_management("KDOT_Roads","INTERSECT","RoadCenterline","60 Feet","NEW_SELECTION") FeatureClassToFeatureClass_conversion("KDOT_Roads",checkfile+r"/NG911","KDOT_Roads_Review","#","#","#") def ConflateKDOT(gdb, DOTRoads): """detects road centerline changes and transfers the HPMS key field from the KDOT roads via ESRI conflation tools""" from arcpy import TransferAttributes_edit, DetectFeatureChanges_management, RubbersheetFeatures_edit, GenerateRubbersheetLinks_edit, RubbersheetFeatures_edit checkfile = gdb spatialtolerance = "20 feet" MakeFeatureLayer_management(DOTRoads+"/KDOT_HPMS_2012","KDOT_Roads","#","#","#") MakeFeatureLayer_management(checkfile+"/RoadCenterline","RoadCenterline","#","#","#") if Exists(checkfile+r"/NG911/KDOT_Roads_Review"): print "selection of KDOT roads for conflation already exists" else: SelectLayerByLocation_management("KDOT_Roads","INTERSECT","RoadCenterline","60 Feet","NEW_SELECTION") FeatureClassToFeatureClass_conversion("KDOT_Roads",checkfile+r"/NG911","KDOT_Roads_Review","#","#","#") MakeFeatureLayer_management(checkfile+"/KDOT_Roads_Review","KDOT_Roads_Review","#","#","#") GenerateRubbersheetLinks_edit("KDOT_Roads_Review","RoadCenterline",checkfile+r"/NG911/RoadLinks",spatialtolerance,"ROUTE_ID LRSKEY",checkfile+r"/RoadMatchTbl") MakeFeatureLayer_management(checkfile+"/NG911/RoadLinks","RoadLinks","#","#","#") MakeFeatureLayer_management(checkfile+"/NG911/RoadLinks_pnt","RoadLinks_pnt","#","#","#") RubbersheetFeatures_edit("KDOT_Roads_Review","RoadLinks","RoadLinks_pnt","LINEAR") DetectFeatureChanges_management("KDOT_Roads_Review","RoadCenterline",checkfile+r"/NG911/RoadDifference",spatialtolerance,"#",checkfile+r"/RoadDifTbl",spatialtolerance,"#") MakeFeatureLayer_management(checkfile+"/NG911/RoadDifference","RoadDifference","#","#","#") TransferAttributes_edit("KDOT_Roads_Review","RoadCenterline","YEAR_RECORD;ROUTE_ID",spatialtolerance,"#",checkfile+r"/LRS_MATCH") def addAdminFields(lyr, Alias): try: AddIndex(lyr,"SEGID;COUNTY_L;COUNTY_R;MUNI_L;MUNI_R","RCL_INDEX","NON_UNIQUE","NON_ASCENDING") except: print "indexed" FieldList3=("KDOT_COUNTY_R", "KDOT_COUNTY_L","KDOT_CITY_R", "KDOT_CITY_L", 'UniqueNo' ) for field in FieldList3: addField(lyr, field, "TEXT", "#", "#", "3") FieldList1=('KDOT_ADMO', 'KDOTPreType', 'PreCode', 'SuffCode', 'TDirCode') for field in FieldList1: addField(lyr, field, "TEXT", "#", "#", "1") addField(lyr, "Soundex", "TEXT", "#", "#", "5") addField(lyr, "RID", "TEXT", "#", "#", "26") addField(lyr, "KDOT_START_DATE", "DATE") addField(lyr, "KDOT_END_DATE", "DATE") addField(lyr, "SHAPE_MILES", "Double", "#", "#", "#" ) addField(Alias, "KDOT_PREFIX", "TEXT", "#", "#", "1" ) addField(Alias, "KDOT_CODE", "LONG" ) addField(Alias, "KDOT_ROUTENAME", "TEXT", "#", "#", "3" ) def CalcAdminFields(lyr, Kdotdbfp): """Populate Admin Fields with Default or Derived values""" CalcField(lyr,"UniqueNo",'000',"PYTHON_9.3","#") CalcField(lyr,"KDOT_START_DATE","1/1/1901","PYTHON_9.3","#") CalcField(lyr,"KDOTPreType","!ROUTE_ID![3]","PYTHON_9.3","#") #PreType is a conflated field, consider changing this to calculate from NENA fields TableView(lyr, "NewPretype", "KDOTPreType is Null") CalcField("NewPretype","KDOTPreType","'L'","PYTHON_9.3","#") CalcField(lyr,"KDOT_ADMO","'X'","PYTHON_9.3","#") CalcField(lyr,"PreCode","0","PYTHON_9.3","#") CalcField(lyr,"KDOT_CITY_L","999","PYTHON_9.3","#") CalcField(lyr,"KDOT_CITY_R","999","PYTHON_9.3","#") CalcField(lyr,"TDirCode","0","PYTHON_9.3","#") CalcField(lyr,"SHAPE_MILES","!Shape_Length!/5280.010560021","PYTHON_9.3","#") #There are slightly more than 5280 miles per US Survey foot TableView(Kdotdbfp+"\\NG911_RdDir", "NG911_RdDir") JoinTbl(lyr,"PRD","NG911_RdDir", "RoadDir", "KEEP_COMMON") CalcField(lyr,"PreCode","!NG911_RdDir.RdDirCode!","PYTHON_9.3","#") removeJoin(lyr) TableView(Kdotdbfp+"\NG911_RdTypes", "NG911_RdTypes") CalcField(lyr,"SuffCode","0","PYTHON_9.3","#") JoinTbl(lyr,"STS","NG911_RdTypes", "RoadTypes", "KEEP_COMMON") CalcField(lyr,"SuffCode","!NG911_RdTypes.LRS_CODE_TXT!","PYTHON_9.3","#") removeJoin(lyr) def CountyCode(lyr): """Codify the County number for LRS (based on right side of street based on addressing direction, calculated for LEFT and RIGHT from NG911)""" TableView(Kdotdbfp+"\NG911_County", "NG911_County") JoinTbl(lyr,"COUNTY_L","NG911_County", "CountyName", "KEEP_COMMON") CalcField(lyr,"KDOT_COUNTY_L","!NG911_County.CountyNumber!","PYTHON_9.3","#") removeJoin(lyr) JoinTbl(lyr,"COUNTY_R","NG911_County", "CountyName", "KEEP_COMMON") CalcField(lyr,"KDOT_COUNTY_R","!NG911_County.CountyNumber!","PYTHON_9.3","#") removeJoin(lyr) def CityCodes(lyr, Kdotdbfp): """Codify the City Limit\city number for LRS , calculated for LEFT and RIGHT from NG911)""" TableView(Kdotdbfp+"\City_Limits", "City_Limits") JoinTbl(lyr,"MUNI_R","City_Limits", "CITY", "KEEP_COMMON") CalcField(lyr,"KDOT_CITY_R","str(!City_Limits.CITY_CD!).zfill(3)","PYTHON_9.3","#") removeJoin(lyr) JoinTbl(lyr,"MUNI_L","City_Limits", "CITY", "KEEP_COMMON") CalcField(lyr,"KDOT_CITY_L","str(!City_Limits.CITY_CD!).zfill(3)","PYTHON_9.3","#") removeJoin(lyr) TableView(lyr, "CityRoads", "KDOT_CITY_R = KDOT_CITY_L AND KDOT_CITY_R not like '999'") CalcField("CityRoads","KDOT_ADMO","'W'","PYTHON_9.3","#") def RoadinName1(lyr): """This module corrects the road names in the soundex code where the road is named like Road A or Road 12 """ TableView(lyr,"ROAD_NAME","RD LIKE 'ROAD %'") CalcField("ROAD_NAME","Soundex",""""R"+!RD![5:].zfill(3)""","PYTHON_9.3","#") TableView(lyr,"RD_NAME","RD LIKE 'RD %'") CalcField(lyr,"Soundex","""("R"+!RD![1:5]).zfill(3)""","PYTHON_9.3","#") def RoadinName(roadFeatures, nameExclusions): """This module corrects the road names in the soundex code where the road is named like Road A or Road 12 """ fieldList = ['OBJECTID', 'RD', 'Soundex'] listMatchString = re.compile(r'^WEST', re.IGNORECASE) roadNameString = '' roadPreSoundexString = '' roadSoundexString = '' testMatch = None testMatch1 = None testMatch2 = None # Get the data from the geodatabase so that it can be used in the next part of the function. cursor = daSearchCursor(roadFeatures, fieldList) # @UndefinedVariable for row in cursor: listRow = list(row) holderList.append(listRow) # Clean up if cursor: del cursor else: pass if row: del row else: pass # Perform some regex on the strings to produce a new soundex in certain cases. for excludedText in nameExclusions: excludedText = str(excludedText) excludedText = excludedText.upper() listMatchString = re.compile(r'^{0}\s'.format(re.escape(excludedText)), re.IGNORECASE) # Matches 1 or 2 alpha characters at the start of a string, ignoring case. singleOrDoubleAlphaMatchString = re.compile(r'^[a-z]$|^[a-z][a-z]$', re.IGNORECASE) # Matches 1 to 4 digits at the start of a string, probably no reason to ignore case in the check. singleToQuadNumberMatchString = re.compile(r'^[0-9]$|^[0-9][0-9]$|^[0-9][0-9][0-9]$|^[0-9][0-9][0-9][0-9]$') for heldRow in holderList: roadNameString = str(heldRow[1]) roadNameString = roadNameString.upper() testMatch = listMatchString.search(roadNameString) if testMatch != None: roadPreSoundexString = roadNameString[testMatch.end():] roadPreSoundexString = roadPreSoundexString.replace(" ", "") # Do subbing for #ST, #ND, #RD, #TH etc... for numberEnding in ordinalNumberEndings: nonsensitiveReplace = re.compile(r'[0-9]{0}'.format(re.escape(numberEnding), re.IGNORECASE)) replaceMatch = nonsensitiveReplace.search(roadNameString) if replaceMatch != None: roadPreSoundexString = re.sub(replaceMatch.group(0), replaceMatch.group(0)[0:1], roadPreSoundexString) else: pass # Test for the following conditions: # A, AA as in Road A, RD AA testMatch1 = None testMatch1 = singleOrDoubleAlphaMatchString.search(roadPreSoundexString) # Test for the following conditions: # 1, 10, 100, 1000 as in Road 1, RD 10, Road 100, CR1000 testMatch2 = None testMatch2 = singleToQuadNumberMatchString.search(roadPreSoundexString) if testMatch1 != None: # Road A, Road BB, or similar. roadPreSoundexString = roadPreSoundexString[testMatch1.start():testMatch1.end()] if len(roadPreSoundexString) > 2: pass elif len(roadPreSoundexString) == 2: roadSoundexString = "0" + roadPreSoundexString # Adds the first letter from the excluded text to the start of the Soundex string. roadSoundexString = excludedText[0:1] + roadSoundexString elif len(roadPreSoundexString) == 1: roadSoundexString = "00" + roadPreSoundexString roadSoundexString = excludedText[0:1] + roadSoundexString else: pass elif(testMatch2 != None): roadPreSoundexString = roadPreSoundexString[testMatch2.start():testMatch2.end()] if len(roadPreSoundexString) > 4: pass elif len(roadPreSoundexString) == 4: # Slice the string to include only the first 3 characters. roadSoundexString = roadPreSoundexString[:4] # Add the first letter from the excluded text to the start of the Soundex string. roadSoundexString = excludedText[0:1] + roadSoundexString elif len(roadPreSoundexString) == 3: roadSoundexString = roadPreSoundexString roadSoundexString = excludedText[0:1] + roadSoundexString elif len(roadPreSoundexString) == 2: roadSoundexString = "0" + roadPreSoundexString roadSoundexString = excludedText[0:1] + roadSoundexString elif len(roadPreSoundexString) == 1: roadSoundexString = "00" + roadPreSoundexString roadSoundexString = excludedText[0:1] + roadSoundexString else: pass # One of the excluded texts was found at the start of the name, but it was not followed by # A, AA, 1, 20, 340, 5670, etc... # Instead something like "Road Hitch" or "RD Empire" # Do soundex normally, but replace the first character with the first character from the # excluded text. else: roadSoundexString = soundex(roadPreSoundexString) # Slice the roadSoundexString to remove the first character, but keep the rest. roadSoundexString = roadSoundexString[1:] # Add the first letter from the excluded text to the start of the Soundex string. roadSoundexString = excludedText[0:1] + roadSoundexString # Assign the new road soundex string to the held row's third slot, heldRow[2], # to be used in an update cursor to update the data in the geodatabase. heldRow[2] = roadSoundexString else: pass # Start an edit session for this workspace because the centerline # feature class participates in a topology. editSession = daEditor(gdb) editSession.startEditing(False, False) editSession.startOperation() cursor = daUpdateCursor(roadFeatures, fieldList) # @UndefinedVariable for row in cursor: for heldRow in holderList: if row[0] == heldRow[0]: cursor.updateRow(heldRow) else: pass # Clean up if cursor: del cursor else: pass if row: del row else: pass editSession.stopOperation() editSession.stopEditing(True) def RouteCalc(lyr, soundexNameExclusions): """calculate what should be a nearly unique LRS Route key based on the decoding and street name soundex/numdex function""" #CalcField(lyr,"Soundex","numdex(!RD!)","PYTHON_9.3","#") RoadinName(lyr, soundexNameExclusions) CalcField(lyr, "RID", "str(!KDOT_COUNTY_R!)+str(!KDOT_COUNTY_L!)+str(!KDOT_CITY_R!)+str(!KDOT_CITY_L!)+str(!PreCode!) + !Soundex! + str(!SuffCode!)+str(!UniqueNo!)+str(!TDirCode!)","PYTHON_9.3","#") # Instead of calling numdex here, rewrite and incorporate numdex and soundex functionality into the RoadinName function. def AliasCalc(Alias, DOTRoads): CalcField(Alias, "KDOT_PREFIX", "!LABEL![0]","PYTHON_9.3","#") CalcField(Alias,"KDOT_ROUTENAME","""!A_RD![1:].replace("S","").zfill(3)""","PYTHON_9.3","#") TableView(DOTRoads+"\KDOT_RoutePre", "KDOT_RoutePre") JoinTbl("RoadAlias", "KDOT_PREFIX", "KDOT_RoutePre", "LRSPrefix", "KEEP_COMMON") CalcField("RoadAlias","RoadAlias.KDOT_CODE","!KDOT_RoutePre.PreCode!","PYTHON_9.3","#") removeJoin("RoadAlias") def HighwayCalc(lyr, gdb, Alias): """Pull out State Highways to preserve KDOT LRS Key (CANSYS FORMAT - non directional CRAD)""" if Exists(gdb+"\RoadAlias_Sort"): Delete(gdb+"\RoadAlias_Sort") else: pass Sort_management(Alias,gdb+"\RoadAlias_Sort","KDOT_CODE ASCENDING;KDOT_ROUTENAME ASCENDING","UR") #Heiarchy did not sort or calc correctly for Cheyenne County, US36 over K161 1st #Sot and join doesnt accomplish primary route key designsation... but calculaing over hte heirarchy should... #Remember to check the primary route heirarchy calculates correctly where US rides US and I rides I Heriarchy = ["K", "U", "I"] for routeClass in Heriarchy: rideselect = "KDOT_PREFIX LIKE '"+routeClass+"%'" print rideselect, routeClass TableView(gdb+"\RoadAlias_Sort", "RoadAlias_Sort", rideselect) JoinTbl(lyr,"SEGID","RoadAlias_Sort", "SEGID", "KEEP_COMMON") CalcField(lyr,lyr+".KDOTPreType","!RoadAlias_Sort.KDOT_PREFIX!","PYTHON_9.3","#") CalcField(lyr,lyr+".Soundex","!RoadAlias_Sort.KDOT_PREFIX!+!RoadAlias_Sort.KDOT_ROUTENAME!","PYTHON_9.3","#") CalcField(lyr,"KDOT_ADMO","'S'","PYTHON_9.3","#") CalcField(lyr,"PreCode","0","PYTHON_9.3","#") removeJoin(lyr) CalcField(lyr, "RID", "str(!KDOT_COUNTY_R!)+str(!KDOT_COUNTY_L!)+str(!KDOT_CITY_R!)+str(!KDOT_CITY_L!)+str(!PreCode!) + !Soundex! + str(!SuffCode!)+str(!UniqueNo!)+str(!TDirCode!)","PYTHON_9.3","#") CalcField(lyr, "LRSKEY", "str(!RID!)", "PYTHON_9.3","#") def ScratchCalcs(): CalcField("RoadCenterline","RoadCenterline.Soundex","""!RoadAlias.A_RD![0] + !RoadAlias.A_RD![1:].replace("S","").zfill(3)""","PYTHON_9.3","#") CalcField(in_table="RoadCenterline",field="RoadCenterline.KDOTPreType",expression="!RoadAlias.A_RD![0] ",expression_type="PYTHON_9.3",code_block="#") CalcField(in_table="RoadCenterline",field="RoadCenterline.PreCode",expression="'0'",expression_type="PYTHON_9.3",code_block="#") CalcField(in_table="RoadCenterline",field="RoadCenterline.KDOT_ADMO",expression="'S'",expression_type="PYTHON_9.3",code_block="#") def LRS_Tester(): """makes the LRS route layer and dissolves the NG911 fields to LRS event tables""" # Replace a layer/table view name with a path to a dataset (which can be a layer file) or create the layer/table view within the script # The following inputs are layers or table views: "RoadCenterline" from arcpy import Dissolve_management as dissolve CalcField(lyr, "LRSKEY", "str(!KDOT_COUNTY_R!)+str(!KDOT_COUNTY_L!)+str(!KDOT_CITY_R!)+str(!KDOT_CITY_L!)+str(!PreCode!) + !Soundex! + str(!SuffCode!)+str(!UniqueNo!)+str(!TDirCode!)","PYTHON_9.3","#") CalcField(lyr, "RID", "str(!KDOT_COUNTY_R!)+str(!KDOT_COUNTY_L!)+str(!KDOT_CITY_R!)+str(!KDOT_CITY_L!)+str(!PreCode!) + !Soundex! + str(!SuffCode!)+str(!UniqueNo!)+str(!TDirCode!)","PYTHON_9.3","#") env.overwriteOutput = 1 dissolve(lyr,gdb+"/NG911/RCLD1","LRSKEY","SEGID COUNT;L_F_ADD MIN;L_T_ADD MAX;L_F_ADD RANGE;L_T_ADD RANGE;SHAPE_MILES SUM","MULTI_PART","DISSOLVE_LINES") dissolve(lyr,gdb+"/NG911/RCLD2","LRSKEY","SEGID COUNT;L_F_ADD MIN;L_T_ADD MAX;L_F_ADD RANGE;L_T_ADD RANGE;SHAPE_MILES SUM","MULTI_PART","UNSPLIT_LINES") #MakeRouteLayer_na() pass uniqueIdInFields = ["OBJECTID", "COUNTY_L", "COUNTY_R", "STATE_L", "STATE_R", "L_F_ADD", "L_T_ADD", "R_F_ADD", "R_T_ADD", "UniqueNo", "LRSKEY", "SHAPE_MILES"] uniqueIdOutFields = ["OBJECTID", "UniqueNo", "LRSKEY"] def createUniqueIdentifier(gdb, lyr, inFieldNamesList, outFieldNamesList): '''filters through records and calculates an incremental Unique Identifier for routes that are not border routes, to handle Y's, eyebrows, and splits that would cause complex routes''' workspaceLocation = gdb #MakeFeatureLayer_management(lyr,"RCL_Particles",where_clause="COUNTY_L = COUNTY_R AND STATE_L = STATE_R AND ( L_F_ADD =0 OR L_T_ADD =0 OR R_F_ADD =0 OR R_T_ADD =0)") featureClassName = lyr from arcpy.da import SearchCursor as daSearchCursor, UpdateCursor as daUpdateCursor, Editor as daEditor alphabetListForConversion = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] newCursor = daSearchCursor(featureClassName, inFieldNamesList) searchList = list() for searchRow in newCursor: searchList.append(list(searchRow)) # Transforms the row tuple into a list so it can be edited. if "newCursor" in locals(): del newCursor else: pass matchCount = 0 matchList = list() for testRow in searchList: if (testRow[1] == testRow[2] and testRow[3] == testRow[4] and (str(testRow[5]) == "0" or str(testRow[6]) == "0" or str(testRow[7]) == "0" or str(testRow[8]) == "0")): matchCount += 1 matchList.append(testRow) matchedRowDictionary = dict() for matchedRow in matchList: matchedRowContainer = list() # If the key already exists, assign the previous list of lists # to the list container, then append the new list # before updating the new value to that key in the dictionary. if matchedRow[10] in matchedRowDictionary: matchedRowContainer = matchedRowDictionary[matchedRow[10]] matchedRowContainer.append(matchedRow) matchedRowDictionary[matchedRow[10]] = matchedRowContainer # Otherwise, the key needs to be created # with the value, the list container, having only # one list contained within it for now. else: matchedRowContainer.append(matchedRow) matchedRowDictionary[matchedRow[10]] = matchedRowContainer for LRSKey in matchedRowDictionary: outRowContainer = matchedRowDictionary[LRSKey] # Sort based on length outRowContainer = sorted(outRowContainer, key = lambda sortingRow: sortingRow[11]) countVariable = 0 # Start at 0 for unique values LRSVariable = "" for outRowIndex, outRow in enumerate(outRowContainer): # Is this the first list/row in the key's list container? # If so, then set the Resolution_Order to 0 if outRowIndex == 0: outRow[9] = 0 else: countVariable += 1 if countVariable in [1, 2, 3, 4, 5, 6, 7, 8, 9]: outRow[9] = countVariable elif countVariable >= 10 and countVariable <= 34: outRow[9] = alphabetListForConversion[countVariable - 10] # Converts countVariable to an alpha character, without the letter "O". else: print "The count Variable is above 34. Ran out of numbers and letters to use as unique values." LRSVariable = outRow[10] LRSVariableShortened = str(LRSVariable[:-1]) # Returns the LRSVariable without the last character. LRSVariable = LRSVariableShortened + str(outRow[9]) outRow[10] = LRSVariable outRowString = "" for outRowElement in outRow: outRowString = outRowString + str(outRowElement) + " " print outRowString outRowContainer[outRowIndex] = outRow matchedRowDictionary[LRSKey] = outRowContainer newEditingSession = daEditor(workspaceLocation) newEditingSession.startEditing() newEditingSession.startOperation() newCursor = daUpdateCursor(featureClassName, outFieldNamesList) # @UndefinedVariable for existingRow in newCursor: formattedOutRow = list() if existingRow[2] in matchedRowDictionary.keys(): outRowContainer = matchedRowDictionary[existingRow[2]] for outRow in outRowContainer: if existingRow[0] == outRow[0]: # Test for matching OBJECTID fields. formattedOutRow.append(outRow[0]) formattedOutRow.append(outRow[9]) formattedOutRow.append(outRow[10]) newCursor.updateRow(formattedOutRow) else: pass else: pass newEditingSession.stopOperation() newEditingSession.stopEditing(True) if "newCursor" in locals(): del newCursor else: pass #ConflateKDOT(gdb, DOTRoads) #addAdminFields(lyr, Alias) #CalcAdminFields(lyr, Kdotdbfp) #CountyCode(lyr) #CityCodes(lyr, Kdotdbfp) RouteCalc(lyr, soundexNameExclusions) #AliasCalc(Alias, DOTRoads) #HighwayCalc(lyr, gdb, Alias) #StreetNetworkCheck(gdb) #createUniqueIdentifier(gdb, lyr, uniqueIdInFields, uniqueIdOutFields) #LRS_Tester()
def removeSmallRoads(): # Going to have to build a list of OIDs for roads # with a Shape length less than or equal to 1500. # Not going to have the SQL information to do a # selection based on a clause. # Could also add a field and then calculate the # length into it prior to running this selection. # Need to make a search cursor that gets the ObjectID and ShapeLength # for each road. # Then, need to add the ObjectID for roads with ShapeLength less than # 1500 to a list, then build SQL queries dynamically to select # and add features from that list, until the list is exhausted # and all features have been selected. print "Removing the small roads from the data." #CopyFeatures_management(countyRoadsFeature, countyRoadsFeaturePrereduction_Q) inMemoryRoadsLayer = 'inMemoryRoadsLayerFC' MakeFeatureLayer_management(countyRoadsFeature, inMemoryRoadsLayer) inMemRoadsFields = ListFields(inMemoryRoadsLayer) for inMemRoadField in inMemRoadsFields: print str(inMemRoadField.name) smallRoadsSCFields = ['ID2', 'Shape@Length'] smallRoadsSearchCursor = daSearchCursor(inMemoryRoadsLayer, smallRoadsSCFields) roadIDsToRemove = list() ''' for smallRoadRow in smallRoadsSearchCursor: if int(str(smallRoadRow[0])) % 500 == 0: print str(smallRoadRow[0]) else: pass raise("Stop error.") ''' for smallRoadRow in smallRoadsSearchCursor: if smallRoadRow[1] <= 1500: roadIDsToRemove.append(smallRoadRow[0]) else: pass roadRemovalCounter = 0 roadsReductionWhereClause = """ "ID2" IN (""" for roadID in roadIDsToRemove: if roadRemovalCounter <= 998: roadsReductionWhereClause = roadsReductionWhereClause + str( roadID) + """, """ roadRemovalCounter += 1 else: # Remove the trailing ", " and add a closing parenthesis. roadsReductionWhereClause = roadsReductionWhereClause[:-2] + """) """ SelectLayerByAttribute_management(inMemoryRoadsLayer, "ADD_TO_SELECTION", roadsReductionWhereClause) # Debug only print "Selecting..." selectedRoadsResult = GetCount_management(inMemoryRoadsLayer) selectedRoadsCount = int(selectedRoadsResult.getOutput(0)) print "Number of roads selected: " + str(selectedRoadsCount) roadRemovalCounter = 0 roadsReductionWhereClause = """ "ID2" IN (""" roadsReductionWhereClause = roadsReductionWhereClause + str( roadID) + """, """ # Remove the trailing ", " and add a closing parenthesis. roadsReductionWhereClause = roadsReductionWhereClause[:-2] + """) """ SelectLayerByAttribute_management(inMemoryRoadsLayer, "ADD_TO_SELECTION", roadsReductionWhereClause) # Debug only print "Selecting..." selectedRoadsResult = GetCount_management(inMemoryRoadsLayer) selectedRoadsCount = int(selectedRoadsResult.getOutput(0)) print "Number of roads selected: " + str(selectedRoadsCount) selectedRoadsResult = GetCount_management(inMemoryRoadsLayer) selectedRoadsCount = int(selectedRoadsResult.getOutput(0)) if selectedRoadsCount >= 1: DeleteFeatures_management(inMemoryRoadsLayer) else: pass
def duplicateNameRemoval(): print "Starting duplicate name removal." newCursor = daSearchCursor(countyRoadNameRosette, countyRoadNameRosetteFieldsObjShape) countyNamePointList = list() for eachPoint in newCursor: countyNamePointList.append(eachPoint) if "newCursor" in locals(): del newCursor else: pass pointDeleteList = list() for pointItem in countyNamePointList: for pointToCheck in countyNamePointList: # If the points share a road name, and a county number, but not the same ObjectID... if pointItem[0] not in pointDeleteList: if pointItem[3] == pointToCheck[3] and str(pointItem[2]).upper() == str(pointToCheck[2]).upper() and (not pointItem[0] == pointToCheck[0]): # Use the distance formula to check to see if these points are within a # certain distance from one another. # If so, add the pointToCheck to the pointDeleteList. distance = 0 point1 = pointItem[1] point2 = pointToCheck[1] distance = calcPointDistance(point1, point2) # Added "and pointToCheck not in pointDeleteList" # to prevent two points from both adding a 3rd point to the list. # Also, the distance looks enormous, but it's only about 1500 meters in Lambert_Conformal_Conic_2SP. # @ 450,000 = maxDistance. -- Check smaller values before implementing, however... # as going from 15000 to 450000 adds a long time to this function's execution. # maybe remove the equality on the upper bound, and change the lower bound # to -1 or something like that. # Change this to add just the objectid to the pointDeleteList # instead of the whole point row to increase the speed # of the check when the list grows to a decent size. # Distance of 10000 seems to give good results. if distance >= 0 and distance < 10000 and pointToCheck[0] not in pointDeleteList: pointDeleteList.append(pointToCheck[0]) else: pass else: pass else: pass newCursor = daUpdateCursor(countyRoadNameRosette, countyRoadNameRosetteFieldsObjShape) for updateableRow in newCursor: for pointToDeleteOID in pointDeleteList: if updateableRow[0] == pointToDeleteOID: print "Selected a point for " + str(updateableRow[2]) + " in " + str(updateableRow[3]) + " county to delete." newCursor.deleteRow() print "Point deleted." else: pass #updateCursor #delete pointToDelete from countyRoadNameRosette. #print a message saying that the point was deleted. if "newCursor" in locals(): del newCursor else: pass
def createShortGradiculeLinesForEachCounty(): # Get/use the same projection as the one used for the county roads. spatialReferenceProjection = Describe( sharedNonStateSystem).spatialReference env.workspace = sqlGdbLocation inputCountyGradicule = countyCountyGradicule bufferedCounties = 'bufferedCounties' countiesToCopy = 'countiesToCopy' gradiculeToCopy = 'gradiculeToCopy' loadedGradiculeCopy = 'loadedGradiculeCopy' loadedTempGradicule = 'loadedTempGradicule' #unBufferedCounties = 'unBufferedCounties' # Using the miniBuffered process changes it from # 1457 total output features to 1481 (at 2.1k) # total output features. miniBufferedCounties = 'miniBufferedCounties' loadedOutputGradicule = 'loadedOutputGradicule' tempCounties = r'in_memory\tempCounties' tempCountyGradicule = r'in_memory\tempCountyGradicule' tempCountyGradiculePostErase = r'in_memory\tempCountyGradiculePostErase' tempCountyGradiculeSinglePart = r'in_memory\tempCountyGradiculeSinglePart' bufferCursorFields = ["OBJECTID", "COUNTY_NAME"] MakeFeatureLayer_management(sharedCounties, countiesToCopy) MakeFeatureLayer_management(countyCountyGradicule, gradiculeToCopy) CopyFeatures_management(gradiculeToCopy, countyGradiculeCopied) MakeFeatureLayer_management(countyGradiculeCopied, loadedGradiculeCopy) # Might be worth dissolving based on COORD & County_Name prior # to removing the County_Name field, if that's a possibility. # Or better yet, just make it so that the Gradicule lines for # a particular county are eligible for intersecting and # erasing with that same county's polygon's. All we're # trying to do here is make it so that the county's original # gradicule lines are about half of their original size. # Don't need to find out which gradicule lines are close to # the county or anything else like that. Just need to reduce # the size of the lines and keep the parts that are nearest # the county that they go with. # Remove the County_Name field so that the intersect can add it # back and populate it only where the county buffer actually # intersects the lines. #DeleteField_management(countyGradiculeCopied, "County_Name") # Elaine requested that this be 1000 Feet shorter. # I made it 2000 feet shorter, because it still seemed too big. Buffer_analysis(sharedCounties, countiesBuffered, "8000 Feet") Buffer_analysis(sharedCounties, countiesMiniBuffered, "1500 Feet") bufferedCountyPolygonList = list() outputFeatureList = list() # 1st SearchCursor newCursor = daSearchCursor(countiesBuffered, bufferCursorFields) for newRow in newCursor: bufferedCountyPolygonList.append(list(newRow)) if 'newCursor' in locals(): del newCursor else: pass MakeFeatureLayer_management(countiesBuffered, bufferedCounties) MakeFeatureLayer_management(countiesMiniBuffered, miniBufferedCounties) loadedCountiesFields = ListFields(bufferedCounties) for loadedCountiesField in loadedCountiesFields: print "A loadedCountiesField was found: " + str( loadedCountiesField.name) countyGradiculeFields = ListFields(loadedGradiculeCopy) for countyGradiculeField in countyGradiculeFields: print "A countyGradiculeField was found: " + str( countyGradiculeField.name) for listedRow in bufferedCountyPolygonList: print str(listedRow) selectCounty = listedRow[1] whereClause = """ "COUNTY_NAME" = '""" + str(selectCounty) + """' """ print "The whereClause is " + str(whereClause) SelectLayerByAttribute_management(bufferedCounties, "NEW_SELECTION", whereClause) SelectLayerByAttribute_management(loadedGradiculeCopy, "NEW_SELECTION", whereClause) Intersect_analysis([loadedGradiculeCopy, bufferedCounties], tempCountyGradicule, "ALL") MultipartToSinglepart_management(tempCountyGradicule, tempCountyGradiculeSinglePart) # Selects the same county as the other Select, but does it from the miniBufferedCounties # so that the lines which lay inside of the county and running just along its edges # are erased, as they should only exist as gradicules for the counties adjoining this # one, but not for this one itself. SelectLayerByAttribute_management(miniBufferedCounties, "NEW_SELECTION", whereClause) MakeFeatureLayer_management(tempCountyGradiculeSinglePart, loadedTempGradicule) SelectLayerByAttribute_management(loadedTempGradicule, "NEW_SELECTION", whereClause) secVerGradiculeFields = ListFields(loadedTempGradicule) #for secVerGradiculeField in secVerGradiculeFields: # print "A secVerGradiculeField was found: " + str(secVerGradiculeField.name) Erase_analysis(loadedTempGradicule, miniBufferedCounties, tempCountyGradiculePostErase, xyToleranceVal) fieldsToCopy = [ "SHAPE@", "County_Number", "County_Name", "DIRECTION", "COORD" ] # 2nd SearchCursor newCursor = daSearchCursor(tempCountyGradiculePostErase, fieldsToCopy) for newRow in newCursor: outputFeatureList.append(newRow) if 'newCursor' in locals(): del newCursor else: pass try: Delete_management(countyGradiculeShortWithUser) except: pass CreateFeatureclass_management(sqlGdbLocation, countyGradiculeShortNoPath, "POLYLINE", "", "", "", spatialReferenceProjection) AddField_management(countyGradiculeShortNoPath, "County_Number", "DOUBLE", "", "", "") AddField_management(countyGradiculeShortNoPath, "County_Name", "TEXT", "", "", "55") AddField_management(countyGradiculeShortNoPath, "DIRECTION", "TEXT", "", "", "5") AddField_management(countyGradiculeShortNoPath, "COORD", "TEXT", "", "", "30") print "First Intersected County Gradicule Row: " + str( outputFeatureList[0]) newCursor = daInsertCursor(countyGradiculeShortPath, fieldsToCopy) counter = 1 for outputFeature in outputFeatureList: rowToInsert = ([outputFeature]) insertedOID = newCursor.insertRow(outputFeature) counter += 1 print "Inserted Row with Object ID of " + str(insertedOID) # Load the feature class. Remove anything shorter than 850 feet. MakeFeatureLayer_management(countyGradiculeShortPath, loadedOutputGradicule) # Select the rows that have geometry which is shorter than 850 feet. ## Note that Shape.STLength() returns units in the projection ## or coordinate system that it the feature class is stored in. whereClause = """ Shape.STLength() < 850 """ print "The whereClause is " + str(whereClause) SelectLayerByAttribute_management(loadedOutputGradicule, "NEW_SELECTION", whereClause) # If there is at least one row selected, delete each selected row. if int(GetCount_management(loadedOutputGradicule).getOutput(0)) > 0: print str(GetCount_management(loadedOutputGradicule).getOutput( 0)) + "rows selected." DeleteRows_management(loadedOutputGradicule) else: print "No rows were selected to delete." if 'newCursor' in locals(): del newCursor else: pass
def transferFeatures(): env.workspace = in_memory featuresToTransfer = list() try: # Create an in_memory feature class which to hold the features from # the Oracle table. FeatureClassToFeatureClass_conversion(kanRoadRCRSRoads, "in_memory", "RCRS") # Then, define a projection on it, since the original Oracle table # is lacking the proper information. DefineProjection_management("in_memory\RCRS", lambertCC) #truncating CDRS segments in KanDrive Spatial print str(datetime.datetime.now() ) + " truncating RCRS segments in KanDrive Spatial." TruncateTable_management(kanDriveSpatialConditions) ############################################################################################################### # Maintainability information: # If you need to add another field to transfer between the two, just add it to both of the # tables and give it the same name in both. ############################################################################################################### # searchCursorFields go to r"in_memory\RCRS". (Input table)(Indirect) descObject = Describe(r"in_memory\RCRS") searchCursorFields = [ field.name for field in descObject.fields if field.name != descObject.OIDFieldName and field.name != "Shape" and field.name != "ID1" ] searchCursorFields.append('SHAPE@') # Make the insertCursor use the same fields as the searchCursor. insertCursorFields = searchCursorFields print "OIDFieldname = " + descObject.OIDFieldName print "fieldNames to be used in the searchCursor (and insertCursor):" for fieldName in searchCursorFields: print fieldName RCRS_SearchCursor = daSearchCursor(r"in_memory\RCRS", searchCursorFields) for RCRS_CursorItem in RCRS_SearchCursor: featureItem = list(RCRS_CursorItem) featuresToTransfer.append(featureItem) RCRS_InsertCursor = daInsertCursor(kanDriveSpatialConditions, insertCursorFields) for RCRS_Feature in featuresToTransfer: insertOID = RCRS_InsertCursor.insertRow(RCRS_Feature) print "Inserted a row with the OID of: " + str(insertOID) except: print "An error occurred." errorItem = sys.exc_info()[1] errorStatement = str(errorItem.args[0]) print errorStatement if len(errorStatement) > 253: errorStatement = errorStatement[0:253] else: pass endTime = datetime.datetime.now() ScriptStatusLogging('KanDrive_Spatial_Conditions_Update', 'kandrive_spatial.DBO.Conditions', scriptFailure, startTime, endTime, errorItem.args[0], pythonLogTable) try: del errorItem except: pass # Reraise the error to stop execution and prevent a success message # from being inserted into the table. raise finally: try: del RCRS_SearchCursor except: pass try: del RCRS_InsertCursor except: pass
def RoadinName(roadFeatures, nameExclusions): """This module corrects the road names in the soundex code where the road is named like Road A or Road 12 """ # Need to add logic to remove the ST from roads like 3RD ST and make sure that this translates to 0003 # and not 003. fieldList = ['OBJECTID', 'RD', 'Soundex'] #Placeholder. Recompiled in nameExclusions for loop. listMatchString = re.compile(r'^WEST', re.IGNORECASE) roadNameString = '' roadPreSoundexString = '' roadSoundexString = '' holderList = list() testMatch0 = None testMatch1 = None testMatch2 = None testMatch3 = None # Get the data from the geodatabase so that it can be used in the next part of the function. cursor = daSearchCursor(roadFeatures, fieldList) # @UndefinedVariable for row in cursor: listRow = list(row) holderList.append(listRow) # Clean up if "cursor" in locals(): del cursor else: pass if "row" in locals(): del row else: pass # Matches any group of 3 alpha characters in the string, ignoring case. tripleAlphaMatchString = re.compile(r'[A-Z][A-Z][A-Z]', re.IGNORECASE) # Matches 1 or 2 alpha characters at the start of a string, ignoring case. singleOrDoubleAlphaMatchString = re.compile(r'^[A-Z]$|^[A-Z][A-Z]$', re.IGNORECASE) # Matches 1 to 4 digits at the start of a string, probably no reason to ignore case in the check. singleToQuadNumberMatchString = re.compile(r'^[0-9]$|^[0-9][0-9]$|^[0-9][0-9][0-9]$|^[0-9][0-9][0-9][0-9]$') anyNumberMatchString = re.compile(r'[0-9]', re.IGNORECASE) # For roads that don't match a name exclusion: singleOrDoubleNumberThenAlphaMatchString = re.compile(r'^[0-9][0-9][A-Z]$|^[0-9][A-Z]$', re.IGNORECASE) # For roads that don't match a name exclusion and should be normally Numdexed. firstCharacterNumberString = re.compile(r'^[0-9]') ## Significant structure change here 2014-11-05. ## Watch for possible bugs. ## ## Added Numdex logic to this part, which ## caused some issues. ## ## Flattened the loops out here so that it only ## does a run through the ## <for heldRow in holderList> ## loop once instead of doing it once per ## entry in the nameExclusions list via ## <for excludedText in nameExclusions> ## ## Runs faster now. After changing the regex string ## to be dynamically generated prior to compilation ## and using \b{0}\b as part of the pattern, ## errors *seem* to be gone. stringToCompile = "" # Perform some regex on the strings to produce a new soundex in certain cases. for i, excludedText in enumerate(nameExclusions): #shift left start excludedText = str(excludedText) excludedText = excludedText.upper() #listMatchString = re.compile(r'^{0}\s'.format(re.escape(excludedText)), re.IGNORECASE) ## Old version, pre-dynamic generation. if i == 0: stringToCompile = r'^\b{0}\b\ '.format(re.escape(excludedText)) else: stringToCompile = stringToCompile + r'|^\b{0}\b\ '.format(re.escape(excludedText)) print i listMatchString = re.compile(stringToCompile, re.IGNORECASE) print "stringToCompile = " + str(stringToCompile) for heldRow in holderList: roadNameString = '' roadPreSoundexString = '' roadSoundexString = '' roadNameString = str(heldRow[1]) roadNameString = roadNameString.upper() roadNameString = roadNameString.replace(".", "") exclusionMatch = listMatchString.search(roadNameString) if exclusionMatch != None: # Testing for excluded Road Names such as "Road" and "CR" in "Road 25" and "CR 2500". # Get the characters from the end of the testMatch to the end of the string. # Should return a string that starts with a space. roadPreSoundexString = roadNameString[exclusionMatch.end():] # Replace with a search for " " by group in regex. roadPreSoundexString = roadPreSoundexString.replace(" ", "") roadPreSoundexString = roadPreSoundexString.replace(" ", "") # then loop through the groups to replace with "" so that any number # of spaces can be removed. print "roadNameString = " + str(roadNameString) print "roadPreSoundexString = " + str(roadPreSoundexString) # Do subbing for #ST, #ND, #RD, #TH etc... for numberEnding in ordinalNumberEndings: nonsensitiveReplace = re.compile(r'[0-9]{0}'.format(re.escape(numberEnding), re.IGNORECASE)) replaceMatch = nonsensitiveReplace.search(roadNameString) if replaceMatch != None: roadPreSoundexString = re.sub(replaceMatch.group(0), "", roadPreSoundexString) else: pass # Replace with regex string that matches spaces as groups, then loop through groups to replace. roadPreSoundexString = roadPreSoundexString.replace(" ", "") roadPreSoundexString = roadPreSoundexString.replace(" ", "") testMatch0 = None testMatch0 = tripleAlphaMatchString.search(roadPreSoundexString) testMatch1 = None testMatch1 = singleOrDoubleAlphaMatchString.search(roadPreSoundexString) testMatch2 = None testMatch2 = singleToQuadNumberMatchString.search(roadPreSoundexString) testMatch3 = None testMatch3 = anyNumberMatchString.search(roadPreSoundexString) if testMatch0 != None: roadSoundexString = soundex(roadPreSoundexString) # Slice the roadSoundexString to remove the first character, but keep the rest. if len(roadSoundexString) >= 4: roadSoundexString = roadSoundexString[1:4] # The next line looks complicated, but exclusionMatch.group(0)[0:1] # is actually just getting the first letter of the first matched pattern. roadSoundexString = exclusionMatch.group(0)[0:1] + roadSoundexString elif len(roadSoundexString) == 3: roadSoundexString = exclusionMatch.group(0)[0:1] + roadSoundexString elif len(roadSoundexString) == 2 or len(roadSoundexString) == 1: roadSoundexString = roadSoundexString.zfill(3) roadSoundexString = exclusionMatch.group(0)[0:1] + roadSoundexString else: pass heldRow[2] = roadSoundexString elif testMatch1 != None: # Road A, Road BB, or similar. roadPreSoundexString = roadPreSoundexString[testMatch1.start():testMatch1.end()] if len(roadPreSoundexString) > 2: pass elif len(roadPreSoundexString) == 2: roadSoundexString = "0" + roadPreSoundexString roadSoundexString = exclusionMatch.group(0)[0:1] + roadSoundexString heldRow[2] = roadSoundexString elif len(roadPreSoundexString) == 1: roadSoundexString = "00" + roadPreSoundexString roadSoundexString = exclusionMatch.group(0)[0:1] + roadSoundexString heldRow[2] = roadSoundexString else: pass elif testMatch2 != None: roadPreSoundexString = roadPreSoundexString[testMatch2.start():testMatch2.end()] if len(roadPreSoundexString) > 4: pass elif len(roadPreSoundexString) == 4: # Slice the string to include only the first 3 characters, as slice end is non-inclusive. roadSoundexString = roadPreSoundexString[:4] roadSoundexString = exclusionMatch.group(0)[0:1] + roadSoundexString heldRow[2] = roadSoundexString elif len(roadPreSoundexString) == 3: roadSoundexString = roadPreSoundexString roadSoundexString = exclusionMatch.group(0)[0:1] + roadSoundexString heldRow[2] = roadSoundexString elif len(roadPreSoundexString) == 2: roadSoundexString = "0" + roadPreSoundexString roadSoundexString = exclusionMatch.group(0)[0:1] + roadSoundexString heldRow[2] = roadSoundexString elif len(roadPreSoundexString) == 1: roadSoundexString = "00" + roadPreSoundexString roadSoundexString = exclusionMatch.group(0)[0:1] + roadSoundexString heldRow[2] = roadSoundexString else: pass else: pass else: roadNameString = heldRow[1] testMatch4 = None testMatch4 = singleOrDoubleNumberThenAlphaMatchString.search(roadNameString) testMatch5 = None testMatch5 = firstCharacterNumberString.search(roadNameString) # Numdex with one or two numbers, then alpha. if testMatch4 != None: roadPreSoundexString = roadNameString[testMatch4.start():] roadSoundexString = roadPreSoundexString.zfill(4) heldRow[2] = roadSoundexString # Normal Numdex if there were not one or two numbers, then alpha, but the string starts with a number. elif testMatch5 != None: numerical_re = re.compile("[A-Z]|[^0-9][^0-9][^0-9][^0-9]") roadPreSoundexString = roadNameString.replace(" ", "") roadSoundexString = re.sub(numerical_re,"", roadPreSoundexString.zfill(4)) if len(roadSoundexString) > 4: roadSoundexString = roadSoundexString[:5] else: pass roadSoundexString = roadSoundexString.zfill(4) heldRow[2] = roadSoundexString else: # Check for AA, BB, EE, etc without an excluded name in front of it if len(roadNameString) == 2: if roadNameString[0] == roadNameString[1]: roadPreSoundexString = roadNameString roadSoundexString = roadPreSoundexString.zfill(4) else: # Normal Soundex roadPreSoundexString = roadNameString roadSoundexString = soundex(roadPreSoundexString) heldRow[2] = roadSoundexString # shift left end try: # Start an edit session for this workspace because the centerline # feature class participates in a topology. editSession = daEditor(gdb) editSession.startEditing(False, False) editSession.startOperation() print "Editing started." cursor = daUpdateCursor(roadFeatures, fieldList) # @UndefinedVariable for row in cursor: for heldRow in holderList: # N^2 looping, try not to place print statements inside this block. if str(row[0]) == str(heldRow[0]): cursor.updateRow(heldRow) else: pass editSession.stopOperation() editSession.stopEditing(True) print "Editing complete." except Exception as e: print "Failed to update the Soundex values." print e.message print GetMessages(2) finally: # Clean up if "cursor" in locals(): del cursor else: pass if "row" in locals(): del row else: pass
def transferFeatures(): env.workspace = in_memory featuresToTransfer = list() try: print str( datetime.datetime.now()) + ' copying the oracle table to memory' # Create an in_memory feature class which to hold the features from # the Oracle table. FeatureClassToFeatureClass_conversion( sdeCDRS, "in_memory", "CDRS", "#", "ALERT_STATUS <> 3 AND AlertType = 'Road Incident'") # Then, define a projection on it, since the original Oracle table # is lacking the proper information. DefineProjection_management("in_memory\CDRS", lambertCC) #truncating CDRS segments in KanDrive Spatial print str(datetime.datetime.now() ) + " truncating Incident segments in KanDrive Spatial." TruncateTable_management(kanDriveSpatialIncidents) ############################################################################################################### # Maintainability information: # If you need to add another field to transfer between the two, just add it to both of the # tables and give it the same name in both. # If you need to add another field to just one, the list comprehension will automatically # exclude it. # # If you need to add another field to transfer between the two and it has to be named # different things in each table, you will need to append the matching name to the searchCursorFields list # and insertCursorFields list are generated. # # I.e. if you add a field named "snowFlakeCount" to the CDRS_ALERT_ROUTE table and a field named # "snowFlakeCounter" to the kandrive_spatial.DBO.Incidents table, you would need to append # "snowFlakeCount" to the searchCursorFields and "snowFlakeCounter" to the insertCursorFields for # them to match up and transfer properly. -- If possible, avoid this by naming them both the same thing. # # If you're having to do several appends, it may be best to just write out all of the field names for # each list in the order that you would like for them to be transfered. This is how the field names # are listed in the Kandrive_Construction_Update.py script. ############################################################################################################### CDRS_Desc_Object = Describe(r"in_memory\CDRS") CDRS_Desc_Fields = [field.name for field in CDRS_Desc_Object.fields] Incidents_Desc_Object = Describe(kanDriveSpatialIncidents) Incidents_Desc_Fields = [ field.name for field in Incidents_Desc_Object.fields ] # This Python list comprehension creates the intersection of the two *_Fields lists # and makes sure that the Shape field and Object ID fields are not directly # transfered. -- The 'SHAPE@' token indirectly transfers the geometry instead # and the Object ID of the target feature class is automatically calculated # by the insert cursor. searchCursorFields = [ fieldName for fieldName in CDRS_Desc_Fields if fieldName in Incidents_Desc_Fields and fieldName != CDRS_Desc_Object.OIDFieldName and fieldName != Incidents_Desc_Object.OIDFieldName and fieldName != 'Shape' ] searchCursorFields.append('SHAPE@') # Make the insertCursor use the same fields as the searchCursor. insertCursorFields = searchCursorFields print "OIDFieldnames: " + CDRS_Desc_Object.OIDFieldName + " & " + Incidents_Desc_Object.OIDFieldName + "." print "fieldNames to be used in the searchCursor (and insertCursor):" for fieldName in searchCursorFields: print fieldName Incidents_Where_Clause = "ALERT_TYPE_TXT = 'Road Incident'" CDRS_SearchCursor = daSearchCursor(r"in_memory\CDRS", searchCursorFields, Incidents_Where_Clause) for CDRS_CursorItem in CDRS_SearchCursor: featureItem = list(CDRS_CursorItem) featuresToTransfer.append(featureItem) ##Debug for feature in featuresToTransfer: print feature ## Incidents_InsertCursor = daInsertCursor(kanDriveSpatialIncidents, insertCursorFields) for CDRS_Feature in featuresToTransfer: insertOID = Incidents_InsertCursor.insertRow(CDRS_Feature) print "Inserted a row with the OID of: " + str(insertOID) ''' print "fieldNames to be used in the searchCursor:" for fieldName in searchCursorFields: print fieldName incidents_Where_Clause = "AlertType = 'Road Incident'" Construction_SearchCursor = daSearchCursor(sdeCDRS, searchCursorFields, incidents_Where_Clause) for Construction_CursorItem in Construction_SearchCursor: featureItem = list(Construction_CursorItem) featuresToTransfer.append(featureItem) Incidents_InsertCursor = daInsertCursor(kanDriveSpatialIncidents, insertCursorFields) for Construction_Feature in featuresToTransfer: insertOID = Incidents_InsertCursor.insertRow(Construction_Feature) print "Inserted a row with the OID of: " + str(insertOID) ''' except: print "An error occurred." errorItem = sys.exc_info()[1] errorStatement = str(errorItem.args[0]) print errorStatement if len(errorStatement) > 253: errorStatement = errorStatement[0:253] else: pass endTime = datetime.datetime.now() ScriptStatusLogging('KanDrive_Spatial_Incidents_Update', 'kandrive_spatial.DBO.Incidents', scriptFailure, startTime, endTime, errorItem.args[0], pythonLogTable) try: del errorItem except: pass # Reraise the error to stop execution and prevent a success message # from being inserted into the table. raise finally: try: del CDRS_SearchCursor except: pass try: del Incidents_InsertCursor except: pass
def TnA(): try: env.workspace = stagews # copying oracle tables to memory print str(datetime.datetime.now()) + " copying oracle tables to memory" FeatureClassToFeatureClass_conversion(sdeCDRS, "in_memory", "Construction", "#", "ALERT_STATUS <> 3") MakeQueryTable_management( sdeCDRSWZ, "wz1", "USE_KEY_FIELDS", "KANROAD.CDRS_WZ_DETAIL.CDRS_WZ_DETAIL_ID", """KANROAD.CDRS_WZ_DETAIL.CDRS_WZ_DETAIL_ID #;KANROAD.CDRS_WZ_DETAIL.CDRS_DETOUR_TYPE_ID #; KANROAD.CDRS_WZ_DETAIL.WORK_ZONE_DESC #;KANROAD.CDRS_WZ_DETAIL.WORK_ZONE_SPEED_RESTRIC #; KANROAD.CDRS_WZ_DETAIL.DETOUR_TYPE_TXT #;KANROAD.CDRS_WZ_DETAIL.DETOUR_SPEED_RESTRIC #; KANROAD.CDRS_WZ_DETAIL.DETOUR_DESC #""", "#", ) TableToTable_conversion("wz1", "in_memory", "wz") # Joining the Oracle CDRS WZ table print str(datetime.datetime.now()) + " Joining the Oracle CDRS WZ table" MakeFeatureLayer_management("Construction", "ConstJoin") AddJoin_management( "ConstJoin", "CDRS_WZ_DETAIL_ID", "wz", "KANROAD_CDRS_WZ_DETAIL_CDRS_WZ_DETAIL_ID", "KEEP_ALL" ) FeatureClassToFeatureClass_conversion("ConstJoin", "in_memory", "CDRS", "#", "ConstJoin.ALERT_STATUS < 3", "#") # reformatting the Route name for US routes print str(datetime.datetime.now()) + " reformatting the Route name for US routes" AddField_management("CDRS", "RouteName", "TEXT", "#", "10") routenamed = ( '!Construction_BEG_LRS_ROUTE![0:1] +str(!Construction_BEG_LRS_ROUTE![3:6]).lstrip("0")' ) # calculation expression # Calculate the Route names for User Display print routenamed CalculateField_management("CDRS", "RouteName", routenamed, "PYTHON_9.3", "#") AddField_management("CDRS", "STATUS", "TEXT", "#", "10") AddField_management("CDRS", "Alert_Status_I", "LONG", "#", "#") CalculateField_management("CDRS", "Alert_Status_I", "!Construction_ALERT_STATUS!", "PYTHON_9.3", "#") # Assigning projection for KanRoad CDRS Alert Route Layer print str(datetime.datetime.now()) + " Assigning projection for KanRoad CDRS Alert Route Layer" DefineProjection_management("CDRS", lambertCC) # reformatting the Route name for US routes print str(datetime.datetime.now()) + " reformatting the Route name for US routes" MakeFeatureLayer_management("CDRS", "ACTIVERoutes", '"Construction_ALERT_STATUS" = 2') CalculateField_management("ACTIVERoutes", "STATUS", '"Active"', "PYTHON_9.3", "#") MakeFeatureLayer_management( "CDRS", "ClosedRoutes", '"Construction_ALERT_STATUS" = 2 AND "Construction_FEA_CLOSED" = 1' ) CalculateField_management("ClosedRoutes", "STATUS", '"Closed"', "PYTHON_9.3", "#") MakeFeatureLayer_management("CDRS", "PlannedRoutes", '"Construction_ALERT_STATUS" = 1') CalculateField_management("PlannedRoutes", "STATUS", '"Planned"', "PYTHON_9.3", "#") # copying joined oracle tables to memory for loading in Wichway Schema print str(datetime.datetime.now()) + " copying joined oracle tables to memory for loading in Wichway Schema" FeatureClassToFeatureClass_conversion(sdeKandriveConstruction, "in_memory", "CDRS_Segments", "#", "#") # delete rows in the destination feature class DeleteRows_management("CDRS_Segments") ############################################################################################################### # Maintainability information: # If you need to add another field to transfer between the two, just add it to the searchCursorFields and the # insertCursorFields lists and make sure that it is in the same position in the list order for both of # them. # Besides 'LoadDate', the order does not matter, so long as each field name in the # searchCursorFields has a counterpart in the insertCursorFields and vice versa. # 'LoadDate' should always be last for the insertCursorFields as it is appended to each row after all # of the other items from the searchCursorFields. ############################################################################################################### featuresToTransfer = list() # searchCursorFields go to "in_memory\CDRS". (Input table) searchCursorFields = [ "SHAPE@", "RouteName", "Construction_BEG_STATE_LOGMILE", "Construction_END_STATE_LOGMILE", "Construction_BEG_COUNTY_NAME", "Construction_ALERT_DATE", "Construction_COMP_DATE", "Construction_ALERT_TYPE_TXT", "Construction_ALERT_DESC_TXT", "Construction_VERT_RESTRICTION", "Construction_WIDTH_RESTRICTION", "Construction_TIME_DELAY_TXT", "Construction_PUBLIC_COMMENT", "wz_KANROAD_CDRS_WZ_DETAIL_DETOUR_TYPE_TXT", "wz_KANROAD_CDRS_WZ_DETAIL_DETOUR_DESC", "Construction_CONTACT_NAME", "Construction_CONTACT_PHONE", "Construction_CONTACT_EMAIL", "Construction_ALERT_HYPERLINK", "Alert_Status_I", "Construction_FEA_CLOSED", "STATUS", "Construction_ALERT_DIREC_TXT", "Construction_BEG_LONGITUDE", "Construction_BEG_LATITUDE", ] # insertCursorFields go to sdeKandriveConstruction. (Output table) insertCursorFields = [ "SHAPE@", "RouteName", "BeginMP", "EndMP", "County", "StartDate", "CompDate", "AlertType", "AlertDescription", "HeightLimit", "WidthLimit", "TimeDelay", "Comments", "DetourType", "DetourDescription", "ContactName", "ContactPhone", "ContactEmail", "WebLink", "AlertStatus", "FeaClosed", "Status", "AlertDirectTxt", "X", "Y", "LoadDate", ] cdrsSearchCursor = daSearchCursor(r"in_memory\CDRS", searchCursorFields) for cdrsCursorItem in cdrsSearchCursor: featureItem = list(cdrsCursorItem) featureItem.append(starttime) featuresToTransfer.append(featureItem) RemoveJoin_management("ConstJoin", "wz") # truncating CDRS segments in WICHWAY SPATIAL print str(datetime.datetime.now()) + " truncating CDRS segments in WICHWAY SPATIAL" TruncateTable_management(sdeKandriveConstruction) cdrsInsertCursor = daInsertCursor(sdeKandriveConstruction, insertCursorFields) for cdrsFeature in featuresToTransfer: insertOID = cdrsInsertCursor.insertRow(cdrsFeature) print "Inserted a row with the OID of: " + str(insertOID) except: print "An error occurred." errorItem = sys.exc_info()[1] print errorItem.args[0] try: del errorItem except: pass raise finally: try: del cdrsSearchCursor except: pass try: del cdrsInsertCursor except: pass
def createCountyLinesForEachCounty(): inputCountyLines = r'Database Connections\sdedev_GIS_DEV.sde\SHARED.COUNTY_LINES' inputCountyPolygons = r'Database Connections\sdedev_GIS_DEV.sde\SHARED.COUNTIES' dissolvedCountyLines = r'Database Connections\countyMapsSQLSDE.sde\CountyLinesDissolved' bufferedCountyPolygons = r'Database Connections\countyMapsSQLSDE.sde\CountiesBuffered' loadedCounties = 'loadedCounties' tempCountyLines = r'in_memory\tempCountyLines' outputCountyLines = r'Database Connections\countyMapsSQLSDE.sde\CountyLinesIntersected' bufferCursorFields = ["OBJECTID"] # Need to dissolve all of those county lines into one set of lines # then, need to create 105 features that are are intersected # with the polygons from said line dissolve. arcpy.Dissolve_management(inputCountyLines, dissolvedCountyLines) arcpy.Buffer_analysis(inputCountyPolygons, bufferedCountyPolygons, "15500 Feet") bufferedCountyPolygonList = list() outputFeatureList = list() # 1st SearchCursor newCursor = daSearchCursor(bufferedCountyPolygons, bufferCursorFields) for newRow in newCursor: bufferedCountyPolygonList.append(list(newRow)) if 'newCursor' in locals(): del newCursor else: pass arcpy.MakeFeatureLayer_management(bufferedCountyPolygons, loadedCounties) for listedRow in bufferedCountyPolygonList: selectNumber = listedRow[0] whereClause = " \"OBJECTID\" = '" + str(selectNumber) + "' " arcpy.SelectLayerByAttribute_management(loadedCounties, "NEW_SELECTION", whereClause) arcpy.Intersect_analysis([dissolvedCountyLines, loadedCounties], tempCountyLines, "ALL") # 2nd SearchCursor newCursor = daSearchCursor(tempCountyLines, ["SHAPE@", "County_Number", "County_Name"]) for newRow in newCursor: outputFeatureList.append(newRow) if 'newCursor' in locals(): del newCursor else: pass # 1st CreateFeatures_management # 1st, 2nd AddField_management lambertProjectionLocationKansas = r"\\gisdata\ArcGIS\GISdata\NAD_83_Kansas_Lambert_Conformal_Conic_Feet.prj" arcpy.CreateFeatureclass_management(r'Database Connections\countyMapsSQLSDE.sde', "CountyLinesIntersected", "POLYLINE", "", "", "", lambertProjectionLocationKansas) arcpy.AddField_management(outputCountyLines, "County_Number", "DOUBLE", "", "", "") arcpy.AddField_management(outputCountyLines, "County_Name", "TEXT", "", "", "55") print "First Intersected County Row: " + str(outputFeatureList[0]) # 1st InsertCursor # Use this again later. Very useful. -- Will need when trying to deserialize arcpy objects from multiprocessing and # then write them to a feature class, since I'll have to call arcpy.point(array) where array is an x,y coord in a # list format prior to writing them to a gdb or sde. newCursor = daInsertCursor(os.path.join(r'Database Connections\countyMapsSQLSDE.sde', 'CountyLinesIntersected'), ["SHAPE@", "County_Number", "County_Name"]) counter = 1 for outputFeature in outputFeatureList: rowToInsert = ([outputFeature]) insertedOID = newCursor.insertRow(outputFeature) counter += 1 print "Inserted Row with Object ID of " + str(insertedOID) if 'newCursor' in locals(): del newCursor else: pass
def createShortGradiculeLinesForEachCounty(): # Get/use the same projection as the one used for the county roads. spatialReferenceProjection = Describe(sharedNonStateSystem).spatialReference env.workspace = sqlGdbLocation inputCountyGradicule = countyCountyGradicule bufferedCounties = 'bufferedCounties' countiesToCopy = 'countiesToCopy' gradiculeToCopy = 'gradiculeToCopy' loadedGradiculeCopy = 'loadedGradiculeCopy' loadedTempGradicule = 'loadedTempGradicule' #unBufferedCounties = 'unBufferedCounties' # Using the miniBuffered process changes it from # 1457 total output features to 1481 (at 2.1k) # total output features. miniBufferedCounties = 'miniBufferedCounties' loadedOutputGradicule = 'loadedOutputGradicule' tempCounties = r'in_memory\tempCounties' tempCountyGradicule = r'in_memory\tempCountyGradicule' tempCountyGradiculePostErase = r'in_memory\tempCountyGradiculePostErase' tempCountyGradiculeSinglePart = r'in_memory\tempCountyGradiculeSinglePart' bufferCursorFields = ["OBJECTID", "COUNTY_NAME"] MakeFeatureLayer_management(sharedCounties, countiesToCopy) MakeFeatureLayer_management(countyCountyGradicule, gradiculeToCopy) CopyFeatures_management(gradiculeToCopy, countyGradiculeCopied) MakeFeatureLayer_management(countyGradiculeCopied, loadedGradiculeCopy) # Might be worth dissolving based on COORD & County_Name prior # to removing the County_Name field, if that's a possibility. # Or better yet, just make it so that the Gradicule lines for # a particular county are eligible for intersecting and # erasing with that same county's polygon's. All we're # trying to do here is make it so that the county's original # gradicule lines are about half of their original size. # Don't need to find out which gradicule lines are close to # the county or anything else like that. Just need to reduce # the size of the lines and keep the parts that are nearest # the county that they go with. # Remove the County_Name field so that the intersect can add it # back and populate it only where the county buffer actually # intersects the lines. #DeleteField_management(countyGradiculeCopied, "County_Name") # Elaine requested that this be 1000 Feet shorter. # I made it 2000 feet shorter, because it still seemed too big. Buffer_analysis(sharedCounties, countiesBuffered, "8000 Feet") Buffer_analysis(sharedCounties, countiesMiniBuffered, "1500 Feet") bufferedCountyPolygonList = list() outputFeatureList = list() # 1st SearchCursor newCursor = daSearchCursor(countiesBuffered, bufferCursorFields) for newRow in newCursor: bufferedCountyPolygonList.append(list(newRow)) if 'newCursor' in locals(): del newCursor else: pass MakeFeatureLayer_management(countiesBuffered, bufferedCounties) MakeFeatureLayer_management(countiesMiniBuffered, miniBufferedCounties) loadedCountiesFields = ListFields(bufferedCounties) for loadedCountiesField in loadedCountiesFields: print "A loadedCountiesField was found: " + str(loadedCountiesField.name) countyGradiculeFields = ListFields(loadedGradiculeCopy) for countyGradiculeField in countyGradiculeFields: print "A countyGradiculeField was found: " + str(countyGradiculeField.name) for listedRow in bufferedCountyPolygonList: print str(listedRow) selectCounty = listedRow[1] whereClause = """ "COUNTY_NAME" = '""" + str(selectCounty) + """' """ print "The whereClause is " + str(whereClause) SelectLayerByAttribute_management(bufferedCounties, "NEW_SELECTION", whereClause) SelectLayerByAttribute_management(loadedGradiculeCopy, "NEW_SELECTION", whereClause) Intersect_analysis([loadedGradiculeCopy, bufferedCounties], tempCountyGradicule, "ALL") MultipartToSinglepart_management(tempCountyGradicule, tempCountyGradiculeSinglePart) # Selects the same county as the other Select, but does it from the miniBufferedCounties # so that the lines which lay inside of the county and running just along its edges # are erased, as they should only exist as gradicules for the counties adjoining this # one, but not for this one itself. SelectLayerByAttribute_management(miniBufferedCounties, "NEW_SELECTION", whereClause) MakeFeatureLayer_management(tempCountyGradiculeSinglePart, loadedTempGradicule) SelectLayerByAttribute_management(loadedTempGradicule, "NEW_SELECTION", whereClause) secVerGradiculeFields = ListFields(loadedTempGradicule) #for secVerGradiculeField in secVerGradiculeFields: # print "A secVerGradiculeField was found: " + str(secVerGradiculeField.name) Erase_analysis(loadedTempGradicule, miniBufferedCounties, tempCountyGradiculePostErase, xyToleranceVal) fieldsToCopy = ["SHAPE@", "County_Number", "County_Name", "DIRECTION", "COORD"] # 2nd SearchCursor newCursor = daSearchCursor(tempCountyGradiculePostErase, fieldsToCopy) for newRow in newCursor: outputFeatureList.append(newRow) if 'newCursor' in locals(): del newCursor else: pass try: Delete_management(countyGradiculeShortWithUser) except: pass CreateFeatureclass_management(sqlGdbLocation, countyGradiculeShortNoPath, "POLYLINE", "", "", "", spatialReferenceProjection) AddField_management(countyGradiculeShortNoPath, "County_Number", "DOUBLE", "", "", "") AddField_management(countyGradiculeShortNoPath, "County_Name", "TEXT", "", "", "55") AddField_management(countyGradiculeShortNoPath, "DIRECTION", "TEXT", "", "", "5") AddField_management(countyGradiculeShortNoPath, "COORD", "TEXT", "", "", "30") print "First Intersected County Gradicule Row: " + str(outputFeatureList[0]) newCursor = daInsertCursor(countyGradiculeShortPath, fieldsToCopy) counter = 1 for outputFeature in outputFeatureList: rowToInsert = ([outputFeature]) insertedOID = newCursor.insertRow(outputFeature) counter += 1 print "Inserted Row with Object ID of " + str(insertedOID) # Load the feature class. Remove anything shorter than 850 feet. MakeFeatureLayer_management(countyGradiculeShortPath, loadedOutputGradicule) # Select the rows that have geometry which is shorter than 850 feet. ## Note that Shape.STLength() returns units in the projection ## or coordinate system that it the feature class is stored in. whereClause = """ Shape.STLength() < 850 """ print "The whereClause is " + str(whereClause) SelectLayerByAttribute_management(loadedOutputGradicule, "NEW_SELECTION", whereClause) # If there is at least one row selected, delete each selected row. if int(GetCount_management(loadedOutputGradicule).getOutput(0)) > 0: print str(GetCount_management(loadedOutputGradicule).getOutput(0)) + "rows selected." DeleteRows_management(loadedOutputGradicule) else: print "No rows were selected to delete." if 'newCursor' in locals(): del newCursor else: pass
def labelAngleNormalization(): if "COUNTY_NAME" not in arcpy.ListFields(countyRoadNameRosette): arcpy.AddField_management(countyRoadNameRosette, "COUNTY_NAME", "TEXT", "", "", "55") else: pass newCursor = daSearchCursor(countyBorderFeature, countyBorderFields) countyTranslationDictionary = dict() for countyBorderItem in newCursor: if countyBorderItem[4] not in countyTranslationDictionary: countyTranslationDictionary[countyBorderItem[4]] = countyBorderItem[3] else: pass if "newCursor" in locals(): del newCursor else: pass newCursor = daUpdateCursor(countyRoadNameRosette, countyRoadNameRosetteFields) for countyPointItem in newCursor: countyPointItem = list(countyPointItem) # Takes the remainder of the angle divided by 360. countyPointItem[0] = math.fmod(countyPointItem[0], 360) # Uses fmod due to floating point issues with the modulo operator in python. if countyPointItem[0] >= 250 and countyPointItem[0] <= 290: countyPointItem[0] = 270 if countyPointItem[2] in countyTranslationDictionary: countyPointItem[1] = countyTranslationDictionary[countyPointItem[2]] else: countyPointItem[1] = "" newCursor.updateRow(countyPointItem) elif countyPointItem[0] >= 160 and countyPointItem[0] <= 200: countyPointItem[0] = 180 if countyPointItem[2] in countyTranslationDictionary: countyPointItem[1] = countyTranslationDictionary[countyPointItem[2]] else: countyPointItem[1] = "" newCursor.updateRow(countyPointItem) elif countyPointItem[0] >= 70 and countyPointItem[0] <= 110: countyPointItem[0] = 90 if countyPointItem[2] in countyTranslationDictionary: countyPointItem[1] = countyTranslationDictionary[countyPointItem[2]] else: countyPointItem[1] = "" newCursor.updateRow(countyPointItem) elif (countyPointItem[0] >= 0 and countyPointItem[0] <= 20) or (countyPointItem[0] >= 340 and countyPointItem[0] <= 360): countyPointItem[0] = 0 if countyPointItem[2] in countyTranslationDictionary: countyPointItem[1] = countyTranslationDictionary[countyPointItem[2]] else: countyPointItem[1] = "" newCursor.updateRow(countyPointItem) else: print "Deleting row for having an angle more than 20 degrees away from a cardinal direction." newCursor.deleteRow() if "newCursor" in locals(): del newCursor else: pass print "Label angle normalization complete!" print "Done extending and intersecting road features." # Need to break this into two pieces and pass some of the inmemorylayers
def localRouteNumbering(): tempDesc = Describe(routeFeaturesFC) print("Calculating LRS Key sub-parts for features in " + returnFeatureClass(tempDesc.catalogPath) + ".") OIDFieldName = tempDesc.OIDFieldName try: del tempDesc except: pass # ReAdd the fields that we're interested in, in the correct order. # sortPointDist will be appended later, making it [-1] and 'LRS_UNIQUE_IDENT1' will be [-2]. fieldsToUse = [ OIDFieldName, 'SHAPE@', 'LABEL', 'LRS_ROUTE_PREFIX', 'LRS_ROUTE_NUM', 'LRS_UNIQUE_IDENT', 'LRS_UNIQUE_IDENT1' ] currentFields = fieldsToUse shapeTokenPosition = 1 uniqueCountyCodeDict = dict() countyCodeFieldsList = ['KDOT_COUNTY_L', 'KDOT_COUNTY_R'] newCursor = daSearchCursor(routeFeaturesFC, countyCodeFieldsList) for cursorRow in newCursor: uniqueCountyCodeDict[str(cursorRow[0])] = 1 uniqueCountyCodeDict[str(cursorRow[1])] = 1 try: del newCursor except: pass uniqueCountyCodeList = list() for uniqueCountyCode in uniqueCountyCodeDict.keys(): uniqueCountyCodeList.append(uniqueCountyCode) try: del uniqueCountyCodeDict except: pass try: uniqueCountyCodeList.remove('None') except: pass sortedUniqueCountyCodes = sorted( uniqueCountyCodeList ) # No need to specify a key since it's one column. for uniqueCountyCodeItem in sortedUniqueCountyCodes: print('Selecting features based on countyCode: ' + str(uniqueCountyCodeItem) + '.') routeFeaturesList = list() uniqueLabelDict = dict() # This should include a check for LRS_PREFIX = 'L' when the KDOT_LRS_KEY IS NULL, instead of taking everything that has a NULL # KDOT LRS_KEY. Need another parenthesis to group the condition inside the current parenthesis. selectionQuery1 = """ KDOT_COUNTY_L = '""" + str( uniqueCountyCodeItem ) + """' AND ((KDOT_LRS_KEY IS NULL AND LRS_PREFIX = 'L') OR KDOT_LRS_KEY LIKE '%L%') """ selectionQuery2 = """ KDOT_COUNTY_L IS NULL AND KDOT_COUNTY_R = '""" + str( uniqueCountyCodeItem ) + """' AND ((KDOT_LRS_KEY IS NULL AND LRS_PREFIX = 'L') OR KDOT_LRS_KEY LIKE '%L%') """ labelField = ['LABEL'] newCursor = daSearchCursor(routeFeaturesFC, labelField, selectionQuery1) for cursorRow in newCursor: uniqueLabelDict[str(cursorRow[0])] = 1 try: del newCursor except: pass newCursor = daSearchCursor(routeFeaturesFC, labelField, selectionQuery2) for cursorRow in newCursor: uniqueLabelDict[str(cursorRow[0])] = 1 try: del newCursor except: pass countyLocalNumber = 0 # Narrow the features that are looked at further. ### Change this to just give you the features instead of ### ### cursoring them back out. ### ### Figure out a way to create dicts/lists that store the features ### in the way that you want them instead of having to run another ### separate pair of selects after this. for uniqueLabelKey in uniqueLabelDict.keys(): if uniqueLabelKey is not 'None': # Labels with single quotes cause problems in selections. if str.find(uniqueLabelKey, "'") > -1: # So, escape them by replacing individual single quotes with double single quotes. uniqueLabelKey = str.replace(uniqueLabelKey, "'", "''") else: pass print("Using the LABEL field value of: " + str(uniqueLabelKey) + ".") countyLocalNumber += 1 selectionQuery3 = selectionQuery1 + """ AND LABEL = '""" + str( uniqueLabelKey) + """' """ selectionQuery4 = selectionQuery2 + """ AND LABEL = '""" + str( uniqueLabelKey) + """' """ labeledRouteFeaturesList = list() firstCounter = 0 newCursor = daSearchCursor(routeFeaturesFC, currentFields, selectionQuery3) for cursorRow in newCursor: firstCounter += 1 labeledRouteFeaturesList.append(list(cursorRow)) try: del newCursor except: pass print("FirstCounter found : " + str(firstCounter) + " segments.") secondCounter = 0 newCursor = daSearchCursor(routeFeaturesFC, currentFields, selectionQuery4) for cursorRow in newCursor: secondCounter += 1 labeledRouteFeaturesList.append(list(cursorRow)) try: del newCursor except: pass print("SecondCounter found : " + str(secondCounter) + " segments.") sortedLabeledRouteFeaturesList = addDistanceAndSort( labeledRouteFeaturesList, shapeTokenPosition) del labeledRouteFeaturesList labelUniqueNumber = 0 previousFeatureGeom = None outputFeaturesDict = dict() for sortedLabeledRouteFeatureItem in sortedLabeledRouteFeaturesList: if previousFeatureGeom == None: # This is the first feature of this label. # Don't need to check for incrementing the labelUniqueNumber. # Just assign the current countyLocalNumber to this feature. # Then, set the previousFeatureGeom to this feature's shape. previousFeatureGeom = sortedLabeledRouteFeatureItem[ shapeTokenPosition] else: # Check to see if this feature's firstpoint or lastpoint are # a match for the previous feature's firstpoint or lastpoint. thisFeatureGeom = sortedLabeledRouteFeatureItem[ shapeTokenPosition] ## This part needs work because it always fails. :(. ## Create a function to check the arrays for relevant matching values instead. ## And let it "match" when there are points that are within the feature tolerance ## of one another. The non-matching is most likely a problem with floating point ## math and equalities. -- See videolog lookup C# for ideas, if needed. # Change this to look at math.abs(firstPoint.X - other.firstPoint.X) < 2*Epsilon, # and math.abs(firstPoint.Y - other.firstPoint.Y) < 2*Epsilon # Since each Point is a Python object and they won't have the same # identity in Python when it performs a comparison on them. # The only time that this will work correctly is when you have # two variable names referencing the same object # (in the same memory location). if polylineStartEndPointsMatch( thisFeatureGeom, previousFeatureGeom, currentXYTolerance) == True: # The feature is contiguous without a gap. The labelUniqueNumber doesn't need to be incremented. # Assign the county code as it's routeNumber and the labelUniqueNumber as its unique ID. pass else: # If not, increment the labelUniqueNumber by 1 # prior to assignment on this feature. labelUniqueNumber += 1 # If greater than 99, then you have to split it so that part of it goes into LRS_UNIQUE_IDENT # and part of it goes into LRS_UNIQUE_IDENT1. if labelUniqueNumber > 99: onesAndTens = labelUniqueNumber % 100 hundredsAndThousands = labelUniqueNumber / 100 pass else: onesAndTens = labelUniqueNumber hundredsAndThousands = 0 sortedLabeledRouteFeatureItem[-2] = str( onesAndTens).zfill(2) ## 2 chars sortedLabeledRouteFeatureItem[-3] = str( hundredsAndThousands).zfill( 1 ) ## 2 chars # Should only be 1char, but /shrug sortedLabeledRouteFeatureItem[-4] = str( countyLocalNumber).zfill(5) ## 5 chars # Then, set the previousFeatureGeom to this feature's shape. previousFeatureGeom = sortedLabeledRouteFeatureItem[ shapeTokenPosition] print( "Adding a feature to the outputFeaturesDict with a countyLocalNumber of: " + str(countyLocalNumber) + " and a labelUniqueNumber of: " + str(labelUniqueNumber) + ".") outputFeaturesDict[sortedLabeledRouteFeatureItem[ 0]] = sortedLabeledRouteFeatureItem[:-1] newCursor = daUpdateCursor(routeFeaturesFC, currentFields, selectionQuery3) for cursorRow in newCursor: if cursorRow[0] in outputFeaturesDict.keys(): newCursor.updateRow(outputFeaturesDict[cursorRow[0]]) try: del newCursor except: pass newCursor = daUpdateCursor(routeFeaturesFC, currentFields, selectionQuery4) for cursorRow in newCursor: if cursorRow[0] in outputFeaturesDict.keys(): newCursor.updateRow(outputFeaturesDict[cursorRow[0]]) try: del newCursor except: pass try: del sortedLabeledRouteFeaturesList except: pass else: pass #Cleanup try: del sortedLabeledRouteFeaturesList except: pass try: del sortedLabeledRouteFeaturesList except: pass
def changedFeaturesImport(sourceFeatures, targetFeatures): # 1.) Make an in_memory copy of the centerlines. #### A field map would have to be created for each dissolved feature layer, so it's not really worth it. # 2.) Get a list of all of the unique Keys # 3.) Loop through the list of unique Keys # 4.) For each Key, select all the features with that Key. # 5.) Count selected features. # 6.) Make a new layer or dissolved layer from this selection. # 7.) Count the number of dissolved features. # 8a.) If the number of dissolved features is 0, then append the error to the error file # and go on to the next Key in the loop. # 8b.) Else, spatially select features in the original feature class with 'SHARE_A_LINE_SEGMENT_WITH'. # 9.) From the spatial select, reselect features that have the same Key. # 10.) Count to make sure that at least one feature is selected. # 11.) If so, delete that feature. # 12.) Cursor the features out of the dissolve layer. # 13.) Insert the features from the dissolve layer into the in_memory copy of the centerlines. # 14.) When the loop is complete, save the in_memory copy of the centerlines # to a gdb on disk. # Won't work for shapefiles. Hopefully you're not using those though. targetFeaturesCopy = targetFeatures + '_Copy' try: del targetFeatureLayer except: pass targetFeatureLayer = returnFeatureClass(targetFeaturesCopy) + '_FL' try: del sourceFeatureLayer except: pass sourceFeatureLayer = returnFeatureClass(sourceFeatures) + '_FL' # Perform cleanup to prevent object creation collisions. layersOrFCsToRemove = [targetFeaturesCopy, targetFeatureLayer, sourceFeatureLayer] for layerOrFCItem in layersOrFCstoRemove: if Exists(layerOrFCItem): try: Delete_management(layerOrFCItem) except: pass else: pass # 1a.) Make an copy of the simplified and flipped centerlines to modify with dissolves. CopyFeatures_management(targetFeatures, targetFeaturesCopy) # 1b.) Add the ReviewUser and ReviewInfo fields to the copy if they do not already exist. # That way, the information from the edits can flow through to future edit sessions # and error checks. tfcDesc = Describe(targetFeaturesCopy) tfcFields = tfcDesc.fields tfcFieldNames = [x.name for x in tfcFields] # Check for ReviewUser field in the targetFeaturesCopy, then add it if missing. if 'ReviewUser' not in tfcFieldNames: #ReviewUser (String, 50) AddField_management(targetFeaturesCopy, 'ReviewUser', "TEXT", "", "", 50, 'ReviewUser', nullable) else: pass # Check for ReviewInfo field in the targetFeaturesCopy, then add it if missing. if 'ReviewInfo' not in tfcFieldNames: #ReviewInfo (String, 250) AddField_management(targetFeaturesCopy, 'ReviewInfo', "TEXT", "", "", 250, 'ReviewInfo', nullable) else: pass sourceSelectionQuery = ''' "''' + str(uniqueKeyFieldToUse) + '''" IS NOT NULL AND "''' + str(uniqueKeyFieldToUse) + '''" IN (''' sourceSelectionQuery = sourceSelectionQuery[:-2] + ''') ''' MakeFeatureLayer_management(targetFeaturesCopy, targetFeatureLayer) MakeFeatureLayer_management(sourceFeatures, sourceFeatureLayer) # 2.) Get a list of all of the unique Keys in the source. ############ Modify this process to only get a list of Keys that have more than one feature. ############ everything else can be skipped for the purpose of dissolving. uniqueKeyFieldList = [str(uniqueKeyFieldToUse)] newCursor = daSearchCursor(sourceFeatureLayer, uniqueKeyFieldList) uniqueKeysDict = dict() for cursorRow in newCursor: uniqueKeysDict[str(cursorRow[0])] = 1 try: del newCursor except: pass uniqueKeysList = uniqueKeysDict.keys() try: uniqueKeysList.remove('None') except: print("Could not remove 'None' from the list of uniqueKeys since it was not a part of the list.") print("Unique Key list creation successful.") print('Found ' + str(len(uniqueKeysList)) + ' unique Keys in the changed features.') #Use multiSelection instead. multiSelectionQuery = ''' "''' + str(uniqueKeyFieldToUse) + '''" IS NOT NULL AND "''' + str(uniqueKeyFieldToUse) + '''" IN (''' multiCounter = 0 # 3.) Loop through the list of unique Keys for uniqueKeyItem in uniqueKeysList: # 4.) For groups of 2000 Keys, select all the features with those Keys. if multiCounter <= 1999: multiSelectionQuery += """'""" + str(uniqueKeyItem) + """'""" + """, """ multiCounter += 1 else: # Add the current item multiSelectionQuery += """'""" + str(uniqueKeyItem) + """'""" + """, """ # Then, remove the trailing ", " and add a closing parenthesis. multiSelectionQuery = multiSelectionQuery[:-2] + ''') ''' featureReplacement(sourceFeatureLayer, targetFeatureLayer, multiSelectionQuery) multiSelectionQuery = ''' "''' + str(uniqueKeyFieldToUse) + '''" IS NOT NULL AND "''' + str(uniqueKeyFieldToUse) + '''" IN (''' multiCounter = 0 # After the for loop, if there is still anything remaining which was unselected in the # the previous multiSelectionQuery steps. # Remove the trailing ", " and add a closing parenthesis. multiSelectionQuery = multiSelectionQuery[:-2] + """) """ featureReplacement(sourceFeatureLayer, targetFeatureLayer, multiSelectionQuery)
def transferConstructionWeather(): env.workspace = in_memory featuresToTransfer = list() try: print str( datetime.datetime.now()) + ' copying the oracle table to memory' # Create an in_memory feature class which to hold the features from # the Oracle table. FeatureClassToFeatureClass_conversion(sdeCDRS, "in_memory", "CDRS_Weather", "#") # Then, define a projection on it, since the original Oracle table # is lacking the proper information. DefineProjection_management("in_memory\CDRS_Weather", lambertCC) ############################################################################################################### # Maintainability information: # ToDo: # If you need to add another field to transfer between the two, just add it to the searchCursorFields and the # insertCursorFields lists and make sure that it is in the same position in the list order for both of # them. # Besides 'LoadDate', the order does not matter, so long as each field name in the # searchCursorFields has a counterpart in the insertCursorFields and vice versa. # 'LoadDate' should always be last for the insertCursorFields as it is appended to each row after all # of the other items from the searchCursorFields. ############################################################################################################### # searchCursorFields go to "in_memory\CDRS". (Input table) # Removed 'GEOMETRY', then replaced functionality with 'SHAPE@'. # Also removed 'OBJECTID', 'RPT_BY_NAME', 'RPT_BY_PHONE', # 'RPT_BY_EMAIL', 'CONTACT_NAME', 'CONTACT_PHONE', 'CONTACT_EMAIL', # 'BEG_LATITUDE', 'BEG_LONGITUDE', 'BEG_REF_POST', 'END_REF_POST', # 'END_LATITUDE', 'END_LONGITUDE', 'INTERNAL_COMMENT', # 'WIDTH_RESTRICTION', 'VERT_RESTRICTION', 'WEIGHT_RESTRICTION', # 'SPEED_RESTRICTION', 'PUBLIC_VIEW', 'DCAM_COMMENT', 'DCAM_DATE', # 'DISPLAY_MAP', 'LINE_COLOR', 'CDRS_ALERT_ROUTE_ID', 'ALERT_ID', # 'ALERT_DATE', 'COMP_DATE', 'BEG_COUNTY_NAME', # 'END_LRS_KEY', 'END_LRS_ROUTE', 'END_COUNTY_NAME', # 'BEG_LRS_DIREC_TXT', 'END_LRS_DIREC_TXT', 'TIME_DELAY_TXT', # 'CDRS_WZ_DETAIL_ID', 'CDRS_FHWA_ID', 'CONST_PROJ_NUM', # 'PUBLIC_COMMENT', 'OFFICE_NAME', 'NEW_NOTIFICATION', # 'EMAIL_REMINDER', 'NOTIFICATION_SENT', 'LOC_ENTRY_TYPE', # 'ALERT_HYPERLINK', 'GIS_VIEW', # 'END_COUNTY_NUMBER', 'ALERT_TYPE_TXT', 'ALERT_STATUS', # 'CLOSED_MSG_SENT', 'ALERT_INSERT_DT', 'FEA_CLOSED' # Public Comment is where to get the output text data from. ###################################################################### searchCursorFields = [ 'SHAPE@', 'ADMIN_OWNER', 'BEG_LRS_KEY', 'ALERT_DIREC_TXT', 'ALERT_DESC_TXT', 'BEG_COUNTY_NUMBER', 'BEG_STATE_LOGMILE', 'END_STATE_LOGMILE', 'LENGTH', 'DISTRICT', 'AREA', 'ROUTE', 'BEG_LRS_ROUTE', 'BEG_DESC', 'END_DESC', 'SITE_CR', 'LAST_UPDATE', 'START_DATE', 'EXPIRE_DATE' ] # insertCursorFields go to kandrive_spatial.DBO.Conditions. (Output table) # Removed 'GEOMETRY' and 'GEOMETRY.STLength()', then replaced their # functionality with 'SHAPE@'. # Also removed 'OBJECTID' ###################################################################### insertCursorFields = [ 'SHAPE@', 'ADMIN_OWNER', 'LRS_KEY', 'LANE_DESCRIPTION', 'ROAD_COND_TEXT', 'COUNTY_NO', 'BEG_STATE_LOGMILE', 'END_STATE_LOGMILE', 'SEG_LENGTH_MILES', 'SNOW_DIST', 'SNOW_AREA', 'RD_SUFX_SUBC', 'ROUTE_ID', 'BEG_DESC', 'END_DESC', 'SITE_CR', 'LAST_UPDATE', ### End of directly transfered columns. Next are set columns. 'STALE_MSG', 'UNIQUE_ID', 'RCRS_ROADS_ID', 'SNOW_SUBAREA', 'ROAD_CONDITION', 'RE_OPENING', 'CLOSED_MSG_SENT', 'CLOSED_FROM', 'CLOSED_TO', 'ACCOMMODATION', 'USER_ID', 'CLOSED_COND', 'MSG_CODE', 'LINE_COLOR', 'MSG_SENT', 'SNOW_ICE_CATEGORY', 'RCRSP_VIEW', ## End of set columns. Next are calculated columns 'SEGMENT_ID', 'LRS_PREFIX', 'LRS_SUFFIX', 'LRS_SUBCLASS', 'RT_NUMBER', 'BEG_POINT_DESC', 'END_POINT_DESC', 'RCRSP_DIST', 'SNICE_BEGIN', 'SNICE_END', 'REPORT_TIME', 'ROAD_COND_TIME' ] # 46 Total with 29 following LAST_UPDATE weatherTypesString = "('Flooding', 'Fog', 'Blowing Dust/Smoke', 'Wind Damage')" whereClause = """ALERT_STATUS = 2 AND FEA_CLOSED = 1 AND ALERT_TYPE_TXT = 'Road Closing' AND ALERT_DESC_TXT IN """ + weatherTypesString cdrsSearchCursor = daSearchCursor(r"in_memory\CDRS_Weather", searchCursorFields, whereClause) for cdrsCursorItem in cdrsSearchCursor: featureItem = list(cdrsCursorItem) ## Copied columns copiedFeatureItem = featureItem[:-2] lrsKey = featureItem[2] startDateCDRS = featureItem[-2] startDateStr = startDateCDRS.strftime('%m/%d/%y') expDateCDRS = featureItem[-1] expDateStr = expDateCDRS.strftime('%m/%d/%y') ## Set Columns copiedFeatureItem.append(0) ## STALE_MSG copiedFeatureItem.append(0) ## UNIQUE_ID copiedFeatureItem.append(9999) ## RCRS_ROADS_ID copiedFeatureItem.append(9) ## SNOW_SUBAREA copiedFeatureItem.append( 11) ## ROAD_CONDITION should always == 11, for closed. copiedFeatureItem.append(None) ## RE_OPENING copiedFeatureItem.append(None) ## CLOSED_MSG_SENT copiedFeatureItem.append(None) ## CLOSED_FROM copiedFeatureItem.append(None) ## CLOSED_TO copiedFeatureItem.append(None) ## ACCOMMODATION copiedFeatureItem.append(100) ## USER_ID copiedFeatureItem.append(2) ## CLOSED_COND copiedFeatureItem.append('0000') ## MSG_CODE copiedFeatureItem.append(255) ## LINE_COLOR copiedFeatureItem.append(0) ## MSG_SENT copiedFeatureItem.append(3) ## SNOW_ICE_CATEGORY copiedFeatureItem.append(3) ## RCRSP_VIEW ## Calculated Columns copiedFeatureItem[4] = 'Closed - ' + copiedFeatureItem[ 4] ## ROAD_COND_TEXT copiedFeatureItem.append( copiedFeatureItem[12]) ## SEGMENT_ID = ROUTE_ID copiedFeatureItem.append(lrsKey[3:4]) ## LRS_PREFIX copiedFeatureItem.append(lrsKey[9:10]) ## LRS_SUFFIX copiedFeatureItem.append(lrsKey[-1:]) ## LRS_SUBCLASS rtNumberToFormat = lrsKey[6:9] rtNumberFormatted = int(rtNumberToFormat) copiedFeatureItem.append(rtNumberFormatted) ## RT_NUMBER # Only get the first 60 chars on the next two columns. copiedFeatureItem.append( copiedFeatureItem[13][:60]) ## BEG_POINT_DESC copiedFeatureItem.append( copiedFeatureItem[14][:60]) ## END_POINT_DESC copiedFeatureItem.append(copiedFeatureItem[9]) ## RCRSP_DIST copiedFeatureItem.append(startDateStr + ' 12:04 AM') ## SNICE_BEGIN copiedFeatureItem.append(expDateStr + ' 11:54 PM') ## SNICE_END copiedFeatureItem.append(startDateStr + ' 12:04 AM') ## REPORT_TIME copiedFeatureItem.append(startDateStr + ' 12:04 AM') ## ROAD_COND_TIME featuresToTransfer.append(copiedFeatureItem) RCRS_InsertCursor = daInsertCursor(kanDriveSpatialConditions, insertCursorFields) for RCRS_Feature in featuresToTransfer: insertOID = RCRS_InsertCursor.insertRow(RCRS_Feature) print "Inserted a row with the OID of: " + str(insertOID) except: print "An error occurred." errorItem = sys.exc_info()[1] errorStatement = str(errorItem.args[0]) print errorStatement if len(errorStatement) > 253: errorStatement = errorStatement[0:253] else: pass endTime = datetime.datetime.now() ScriptStatusLogging('KanDrive_Spatial_Conditions_Update', 'kandrive_spatial.DBO.Conditions', scriptFailure, startTime, endTime, errorItem.args[0], pythonLogTable) try: del errorItem except: pass # Reraise the error to stop execution and prevent a success message # from being inserted into the table when the script completes. raise finally: try: del cdrsSearchCursor except: pass try: del RCRS_InsertCursor except: pass
def transferFeatures(): env.workspace = in_memory featuresToTransfer = list() try: print str(datetime.datetime.now()) + ' copying the oracle table to memory' # Create an in_memory feature class which to hold the features from # the Oracle table. FeatureClassToFeatureClass_conversion(sdeCDRS,"in_memory","CDRS","#","ALERT_STATUS <> 3 AND AlertType = 'Road Incident'") # Then, define a projection on it, since the original Oracle table # is lacking the proper information. DefineProjection_management("in_memory\CDRS", lambertCC) #truncating CDRS segments in KanDrive Spatial print str(datetime.datetime.now()) + " truncating Incident segments in KanDrive Spatial." TruncateTable_management(kanDriveSpatialIncidents) ############################################################################################################### # Maintainability information: # If you need to add another field to transfer between the two, just add it to both of the # tables and give it the same name in both. # If you need to add another field to just one, the list comprehension will automatically # exclude it. # # If you need to add another field to transfer between the two and it has to be named # different things in each table, you will need to append the matching name to the searchCursorFields list # and insertCursorFields list are generated. # # I.e. if you add a field named "snowFlakeCount" to the CDRS_ALERT_ROUTE table and a field named # "snowFlakeCounter" to the kandrive_spatial.DBO.Incidents table, you would need to append # "snowFlakeCount" to the searchCursorFields and "snowFlakeCounter" to the insertCursorFields for # them to match up and transfer properly. -- If possible, avoid this by naming them both the same thing. # # If you're having to do several appends, it may be best to just write out all of the field names for # each list in the order that you would like for them to be transfered. This is how the field names # are listed in the Kandrive_Construction_Update.py script. ############################################################################################################### CDRS_Desc_Object = Describe(r"in_memory\CDRS") CDRS_Desc_Fields = [field.name for field in CDRS_Desc_Object.fields] Incidents_Desc_Object = Describe(kanDriveSpatialIncidents) Incidents_Desc_Fields = [field.name for field in Incidents_Desc_Object.fields] # This Python list comprehension creates the intersection of the two *_Fields lists # and makes sure that the Shape field and Object ID fields are not directly # transfered. -- The 'SHAPE@' token indirectly transfers the geometry instead # and the Object ID of the target feature class is automatically calculated # by the insert cursor. searchCursorFields = [fieldName for fieldName in CDRS_Desc_Fields if fieldName in Incidents_Desc_Fields and fieldName != CDRS_Desc_Object.OIDFieldName and fieldName != Incidents_Desc_Object.OIDFieldName and fieldName != 'Shape'] searchCursorFields.append('SHAPE@') # Make the insertCursor use the same fields as the searchCursor. insertCursorFields = searchCursorFields print "OIDFieldnames: " + CDRS_Desc_Object.OIDFieldName + " & " + Incidents_Desc_Object.OIDFieldName + "." print "fieldNames to be used in the searchCursor (and insertCursor):" for fieldName in searchCursorFields: print fieldName Incidents_Where_Clause = "ALERT_TYPE_TXT = 'Road Incident'" CDRS_SearchCursor = daSearchCursor(r"in_memory\CDRS", searchCursorFields, Incidents_Where_Clause) for CDRS_CursorItem in CDRS_SearchCursor: featureItem = list(CDRS_CursorItem) featuresToTransfer.append(featureItem) Incidents_InsertCursor = daInsertCursor(kanDriveSpatialIncidents, insertCursorFields) for CDRS_Feature in featuresToTransfer: insertOID = Incidents_InsertCursor.insertRow(CDRS_Feature) print "Inserted a row with the OID of: " + str(insertOID) ''' print "fieldNames to be used in the searchCursor:" for fieldName in searchCursorFields: print fieldName incidents_Where_Clause = "AlertType = 'Road Incident'" Construction_SearchCursor = daSearchCursor(sdeCDRS, searchCursorFields, incidents_Where_Clause) for Construction_CursorItem in Construction_SearchCursor: featureItem = list(Construction_CursorItem) featuresToTransfer.append(featureItem) Incidents_InsertCursor = daInsertCursor(kanDriveSpatialIncidents, insertCursorFields) for Construction_Feature in featuresToTransfer: insertOID = Incidents_InsertCursor.insertRow(Construction_Feature) print "Inserted a row with the OID of: " + str(insertOID) ''' except: print "An error occurred." errorItem = sys.exc_info()[1] errorStatement = str(errorItem.args[0]) print errorStatement if len(errorStatement) > 253: errorStatement = errorStatement[0:253] else: pass endTime = datetime.datetime.now() ScriptStatusLogging('KanDrive_Spatial_Incidents_Update', 'kandrive_spatial.DBO.Incidents', scriptFailure, startTime, endTime, errorItem.args[0], pythonLogTable) try: del errorItem except: pass # Reraise the error to stop execution and prevent a success message # from being inserted into the table. raise finally: try: del CDRS_SearchCursor except: pass try: del Incidents_InsertCursor except: pass