예제 #1
0
def calculateRampUniqueIdValues():
    layerForRampsSelection = 'layerForRampsSelection'
    MakeFeatureLayer_management(fcToCalculateTargetKeysIn,
                                layerForRampsSelection)
    selectionQuery = """ SourceRouteId LIKE '___X%' OR LRS_ROUTE_PREFIX = 'X' """
    updateFields = ['SourceRouteId', uniqueIdTarget]

    newCursor = daUpdateCursor(fcToCalculateTargetKeysIn, updateFields,
                               selectionQuery)

    for updateItem in newCursor:
        updateListItem = list(updateItem)
        keyToUse = ''
        if updateListItem[0] is not None:
            sourceIdFull = str(updateListItem[0])
            if len(sourceIdFull) >= 11:
                idToUse = sourceIdFull[9:11]
            else:
                idToUse = '00'
        else:
            idToUse = '00'

        updateListItem[1] = idToUse
        newCursor.updateRow(updateListItem)

    try:
        del newCursor
    except:
        pass
예제 #2
0
def prepareAggregateTable():
    env.workspace = in_memory
    
    FeatureClassToFeatureClass_conversion(kanDriveSpatialConditions,"in_memory","aggregateTable")
    rowDeletionCursor = daUpdateCursor(aggregateTable, '*')
    
    for rowToDelete in rowDeletionCursor:
        rowDeletionCursor.deleteRow()
    
    try:
        del rowDeletionCursor
    except:
        pass
예제 #3
0
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 recalculateKeyValues():
    # As long as the KDOT_LRS_KEY is not null, calculate from the
    # current fields.

    # Prior to doing any of this, I added a field to cache the
    # current KDOT_LRS_KEY to check for mistakes and recover from
    # them if any were found.

    # Use the prefix field to decide on what action to take to update the KDOTRouteId.
    # If the prefix is null, do nothing.
    # If the prefix is I, U, K, create the KDOTRouteId value from the SHS component parts.
    selectionQuery = """ "LRS_ROUTE_PREFIX" IN ('I', 'U', 'K') """
    necessaryFields = [
        "LRS_COUNTY_PRE", "LRS_ROUTE_PREFIX", "LRS_ROUTE_NUM",
        "LRS_ROUTE_SUFFIX", "LRS_UNIQUE_IDENT", "KDOT_DIRECTION_CALC"
    ]
    dynNonNullSelectionQuery = GenerateNonNullSelectionQuery(necessaryFields)
    fullSelectionQuery = selectionQuery + """ AND """ + dynNonNullSelectionQuery

    fieldsToUseForUpdating = [
        "LRS_COUNTY_PRE", "LRS_ROUTE_PREFIX", "LRS_ROUTE_NUM",
        "LRS_ROUTE_SUFFIX", "LRS_UNIQUE_IDENT", "KDOT_DIRECTION_CALC",
        "KDOT_LRS_KEY"
    ]

    newCursor = daUpdateCursor(fcAsFeatureLayer, fieldsToUseForUpdating,
                               fullSelectionQuery)

    for cursorRowItem in newCursor:
        cursorListItem = list(cursorRowItem)
        countyPre = cursorListItem[0]
        routePre = cursorListItem[1]
        routeNum = cursorListItem[2]
        routeSuf = cursorListItem[3]
        lrsUniqueIdent = cursorListItem[4]
        if len(lrsUniqueIdent) > 1:
            lrsUniqueIdent = lrsUniqueIdent[-1]
        else:
            pass
        directionCalc = cursorListItem[5]
        directionText = ''

        # Modified 2017-17-27 to fix the issue of non-primary sides, esp. on odd-numbered routes, receiving '-EB'.
        try:
            if int(routeNum) % 2 == 0:
                if directionCalc is not None and int(directionCalc) == 1:
                    directionText = '-WB'
                else:
                    # Default, if the non-primary side is receiving this, make sure that it has a 1 in the directionCalc.
                    directionText = '-EB'

            if int(routeNum) % 2 == 1:
                if directionCalc is not None and int(directionCalc) == 1:
                    directionText = '-SB'
                else:
                    # Default, if the non-primary side is receiving this, make sure that it has a 1 in the directionCalc.
                    directionText = '-NB'
            newKey = str(countyPre) + str(routePre) + str(routeNum) + str(
                routeSuf) + str(lrsUniqueIdent) + directionText
            cursorListItem[6] = newKey
            # For Debugging
            ##print("Updating the lrs key to: " + str(newKey) + ".")
            newCursor.updateRow(cursorListItem)
        except:
            try:
                print(traceback.format_exc())
                print("Could not calculate a new LRS_KEY for the given row.")
                print("The row looks like this: " + str(cursorListItem) + ".")
            except:
                pass
            newCursor.next()

    try:
        del newCursor
    except:
        pass

    ###------------------------------------------------------------------------------------------------------------###
    ### If the prefix is not I, U, K and not X, create the KDOTRouteID from the Non-SHS, Non-Ramp component parts. ###
    ###------------------------------------------------------------------------------------------------------------###

    # For prefix R & M
    selectionQuery = """ "LRS_ROUTE_PREFIX" IN ('R', 'M') """
    necessaryFields = [
        "LRS_COUNTY_PRE", "LRS_ROUTE_PREFIX", "LRS_ROUTE_NUM",
        "LRS_ROUTE_SUFFIX", "LRS_UNIQUE_IDENT", "LRS_ADMO"
    ]
    dynNonNullSelectionQuery = GenerateNonNullSelectionQuery(necessaryFields)
    fullSelectionQuery = selectionQuery + """ AND """ + dynNonNullSelectionQuery

    fieldsToUseForUpdating = [
        "LRS_COUNTY_PRE", "LRS_ROUTE_PREFIX", "LRS_ROUTE_NUM",
        "LRS_ROUTE_SUFFIX", "LRS_UNIQUE_IDENT", "LRS_ADMO",
        "KDOT_DIRECTION_CALC", "KDOT_LRS_KEY"
    ]

    newCursor = daUpdateCursor(fcAsFeatureLayer, fieldsToUseForUpdating,
                               fullSelectionQuery)

    for cursorRowItem in newCursor:
        cursorListItem = list(cursorRowItem)
        countyPre = cursorListItem[0]
        routePre = cursorListItem[1]
        routeNum = cursorListItem[2]
        routeSuf = cursorListItem[3]
        lrsUniqueIdent = cursorListItem[4]
        if len(lrsUniqueIdent) > 1:
            lrsUniqueIdent = lrsUniqueIdent[
                -1]  # Get the right-most value. e.g. 47 => 7, 52 => 2
        else:
            pass
        lrsAdmo = cursorListItem[5]
        directionCalc = cursorListItem[6]
        if directionCalc is None:
            directionCalc = '0'
        else:
            pass
        try:
            newKey = str(countyPre) + str(routePre) + str(routeNum) + str(
                routeSuf) + str(lrsUniqueIdent) + str(lrsAdmo) + str(
                    directionCalc)
            cursorListItem[7] = newKey
            newCursor.updateRow(cursorListItem)
        except:
            try:
                print(traceback.format_exc())
                print("Could not calculate a new LRS_KEY for the given row.")
                print("The row looks like this: " + str(cursorListItem) + ".")
            except:
                pass
            newCursor.next()

    try:
        del newCursor
    except:
        pass

    # For prefix C, Urban Classified, which uses LRS_URBAN_PRE.
    selectionQuery = """ "LRS_ROUTE_PREFIX" IN ('C') """
    necessaryFields = [
        "LRS_URBAN_PRE", "LRS_ROUTE_PREFIX", "LRS_ROUTE_NUM",
        "LRS_ROUTE_SUFFIX", "LRS_UNIQUE_IDENT", "LRS_ADMO"
    ]
    dynNonNullSelectionQuery = GenerateNonNullSelectionQuery(necessaryFields)
    # Uses LRS_ADMO
    ####LRS_ROUTE_NUM, LRS_ROUTE_SUFFIX, LRS_UNIQUE_IDENT, then LRS_ADMO, then 0 for inventory direction.
    fullSelectionQuery = selectionQuery + """ AND """ + dynNonNullSelectionQuery

    fieldsToUseForUpdating = [
        "LRS_URBAN_PRE", "LRS_ROUTE_PREFIX", "LRS_ROUTE_NUM",
        "LRS_ROUTE_SUFFIX", "LRS_UNIQUE_IDENT", "LRS_ADMO",
        "KDOT_DIRECTION_CALC", "KDOT_LRS_KEY"
    ]

    newCursor = daUpdateCursor(fcAsFeatureLayer, fieldsToUseForUpdating,
                               fullSelectionQuery)

    for cursorRowItem in newCursor:
        cursorListItem = list(cursorRowItem)
        urbanPre = cursorListItem[0]
        routePre = cursorListItem[1]
        routeNum = cursorListItem[2]
        routeSuf = cursorListItem[3]
        lrsUniqueIdent = cursorListItem[4]
        if len(lrsUniqueIdent) > 1:
            lrsUniqueIdent = lrsUniqueIdent[
                -1]  # Get the right-most value. e.g. 47 => 7, 52 => 2
        else:
            pass
        lrsAdmo = cursorListItem[5]
        directionCalc = cursorListItem[6]
        if directionCalc is None:
            directionCalc = '0'
        else:
            pass
        try:
            newKey = str(urbanPre) + str(routePre) + str(routeNum) + str(
                routeSuf) + str(lrsUniqueIdent) + str(lrsAdmo) + str(
                    directionCalc)
            cursorListItem[7] = newKey
            newCursor.updateRow(cursorListItem)
        except:
            try:
                print(traceback.format_exc())
                print("Could not calculate a new LRS_KEY for the given row.")
                print("The row looks like this: " + str(cursorListItem) + ".")
            except:
                pass
            newCursor.next()

    try:
        del newCursor
    except:
        pass

    # If the prefix is X, create the KDOTRouteID from the Ramp route component parts.
    selectionQuery = """ "LRS_ROUTE_PREFIX" = 'X' """
    # Doesn't make sense to require *_SUFFIX on ramps. - Just use '0' if it is null.
    # Only 12 Ramps have non-null LRS_ROUTE_SUFFIX values. For those, it is all '0' or 'No Suffix'.
    # If people set LRS_ROUTE_SUFFIX to 'G' or 'Z' for ramps though, that needs to be handled correctly.
    necessaryFields = [
        "LRS_COUNTY_PRE", "LRS_ROUTE_PREFIX", "LRS_ROUTE_NUM",
        "LRS_UNIQUE_IDENT", "LRS_ADMO"
    ]
    dynNonNullSelectionQuery = GenerateNonNullSelectionQuery(necessaryFields)
    fullSelectionQuery = selectionQuery + """ AND """ + dynNonNullSelectionQuery

    fieldsToUseForUpdating = [
        "LRS_COUNTY_PRE", "LRS_ROUTE_PREFIX", "LRS_ROUTE_NUM",
        "LRS_ROUTE_SUFFIX", "LRS_UNIQUE_IDENT", "LRS_ADMO",
        "KDOT_DIRECTION_CALC", "KDOT_LRS_KEY"
    ]

    newCursor = daUpdateCursor(fcAsFeatureLayer, fieldsToUseForUpdating,
                               fullSelectionQuery)

    for cursorRowItem in newCursor:
        cursorListItem = list(cursorRowItem)
        countyPre = cursorListItem[0]
        routePre = cursorListItem[1]
        routeNum = cursorListItem[2]
        routeSuf = cursorListItem[3]
        if routeSuf is None:
            routeSuf = '0'
        else:  # Use whatever character is in the Route Suffix if it's not None/Null.
            pass
        lrsUniqueIdent = cursorListItem[4]
        if len(lrsUniqueIdent) > 1:
            lrsUniqueIdent = lrsUniqueIdent[-1]
        else:
            pass
        lrsAdmo = cursorListItem[5]
        directionCalc = cursorListItem[6]
        if directionCalc is None:
            directionCalc = '0'
        else:
            pass
        try:
            newKey = str(countyPre) + str(routePre) + str(routeNum) + str(
                routeSuf) + str(lrsUniqueIdent) + str(lrsAdmo) + str(
                    directionCalc)
            cursorListItem[7] = newKey
            newCursor.updateRow(cursorListItem)
        except:
            try:
                print(traceback.format_exc())
                print("Could not calculate a new LRS_KEY for the given row.")
                print("The row looks like this: " + str(cursorListItem) + ".")
            except:
                pass
            newCursor.next()

    try:
        del newCursor
    except:
        pass

    # For all other prefixes.
    selectionQuery = """ "LRS_ROUTE_PREFIX" NOT IN ('I', 'U', 'K', 'X', 'R', 'M', 'C') """
    necessaryFields = [
        "LRS_COUNTY_PRE", "LRS_ROUTE_PREFIX", "LRS_ROUTE_NUM",
        "LRS_ROUTE_SUFFIX", "LRS_UNIQUE_IDENT", "LRS_ADMO"
    ]
    dynNonNullSelectionQuery = GenerateNonNullSelectionQuery(necessaryFields)
    fullSelectionQuery = selectionQuery + """ AND """ + dynNonNullSelectionQuery

    fieldsToUseForUpdating = [
        "LRS_COUNTY_PRE", "LRS_ROUTE_PREFIX", "LRS_ROUTE_NUM",
        "LRS_ROUTE_SUFFIX", "LRS_UNIQUE_IDENT", "LRS_ADMO",
        "KDOT_DIRECTION_CALC", "KDOT_LRS_KEY"
    ]

    newCursor = daUpdateCursor(fcAsFeatureLayer, fieldsToUseForUpdating,
                               fullSelectionQuery)

    for cursorRowItem in newCursor:
        cursorListItem = list(cursorRowItem)
        countyPre = cursorListItem[0]
        routePre = cursorListItem[1]
        routeNum = cursorListItem[2]
        routeSuf = cursorListItem[3]
        lrsUniqueIdent = cursorListItem[4]
        if len(lrsUniqueIdent) > 1:
            lrsUniqueIdent = lrsUniqueIdent[-1]
        else:
            pass
        lrsAdmo = cursorListItem[5]
        directionCalc = cursorListItem[6]
        if directionCalc is None:
            directionCalc = '0'
        else:
            pass
        try:
            newKey = str(countyPre) + str(routePre) + str(routeNum) + str(
                routeSuf) + str(lrsUniqueIdent) + str(lrsAdmo) + str(
                    directionCalc)
            cursorListItem[7] = newKey
            newCursor.updateRow(cursorListItem)
        except:
            try:
                print(traceback.format_exc())
                print("Could not calculate a new LRS_KEY for the given row.")
                print("The row looks like this: " + str(cursorListItem) + ".")
            except:
                pass
            newCursor.next()

    try:
        del newCursor
    except:
        pass

    # Something's not right. The calculates should fail every time because the n1 fields don't exist in this layer yet. :(
    selectionQuery = """ "KDOT_LRS_KEY" IS NOT NULL """
    SelectLayerByAttribute_management(fcAsFeatureLayer, "NEW_SELECTION",
                                      selectionQuery)
    # SourceRouteId = KDOT_LRS_KEY
    CalculateField_management(fcAsFeatureLayer, n1RouteId,
                              "!" + str(KDOTRouteId) + "!", "PYTHON_9.3")
    # SourceFromMeasure = county_log_begin
    CalculateField_management(fcAsFeatureLayer, n1FromMeas,
                              "!" + str(KDOTMeasBeg) + "!", "PYTHON_9.3")
    # SourceToMeasure = county_log_end
    CalculateField_management(fcAsFeatureLayer, n1ToMeas,
                              "!" + str(KDOTMeasEnd) + "!", "PYTHON_9.3")
    selectionQuery = """ KDOT_LRS_KEY IS NOT NULL AND county_log_begin IS NULL AND county_log_end IS NULL AND (COUNTY_BEGIN_MP IS NOT NULL OR COUNTY_END_MP IS NOT NULL) """
    SelectLayerByAttribute_management(fcAsFeatureLayer, "NEW_SELECTION",
                                      selectionQuery)
    countResult = GetCount_management(fcAsFeatureLayer)
    intCount = int(countResult.getOutput(0))
    print(
        "After the new selection query to deal with the fact that some State routes did not have their begin and end measure populated correctly, "
        + str(intCount) + " segments were selected.")
    # SourceFromMeasure = COUNTY_BEGIN_MP
    CalculateField_management(fcAsFeatureLayer, n1FromMeas,
                              "!COUNTY_BEGIN_MP!", "PYTHON_9.3")
    # SourceToMeasure = COUNTY_END_MP
    CalculateField_management(fcAsFeatureLayer, n1ToMeas, "!COUNTY_END_MP!",
                              "PYTHON_9.3")
예제 #5
0
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
예제 #6
0
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 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 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 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 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
예제 #11
0
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
예제 #12
0
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
예제 #13
0
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
예제 #14
0
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()
예제 #15
0
def concatFullTargetKeys():
    # County Key Calculation
    # County Code (3) + Prefix (1) + Route number (5) + Suffix (1) + Inventory Direction (1) = 11 characters.
    # County Code (3) + Prefix (1) + Route number (5) + Suffix (1) + Inventory Direction (1) + Unique ID (2) = 13 characters.
    # First, start an update cursor,
    # then update the columns with this format:
    # lrsKeyCountyTarget = countycode.zfill(3) + prefix_target + routenumber_target + suffix + inventorydirection or 0 + unique id (ramp code), or null if not a ramp (PREFIX_TARGET is not 'X') and unique id/ramp code == '00'.
    updateFields = [
        'LRS_COUNTY_PRE', 'ROUTE_PREFIX_TARGET', 'LRS_ROUTE_NUM_TARGET',
        'LRS_ROUTE_SUFFIX', 'LRS_DIRECTION', 'KDOT_DIRECTION_CALC',
        uniqueIdTarget, 'LRS_UNIQUE_IDENT', 'LRS_UNIQUE_IDENT1',
        targetCountyLRSKey
    ]
    # If uniqueID is None OR uniqueID == '00' and prefix_target != 'X',
    # uniqueIDPartForConcat = ''

    newCursor = daUpdateCursor(fcToCalculateTargetKeysIn, updateFields)

    for updateItem in newCursor:
        updateListItem = list(updateItem)
        keyToUse = ''
        if str(updateListItem[0]).lower() != 'none':
            countyPre = updateListItem[0]
        else:
            countyPre = '404'  # County Not Found
        if str(updateListItem[1]).lower() != 'none':
            prefixTarget = updateListItem[1]
        else:
            prefixTarget = '8'  # For 'other'.
        if str(updateListItem[2]).lower() != 'none':
            routeNumTarget = updateListItem[2]
        else:
            routeNumTarget = str('').zfill(5)
        if str(updateListItem[3]).lower() != 'none':
            if updateListItem[1] in ('1', '2', '3', '4', '5', '6'):
                routeSuffix = updateListItem[3]
            elif updateListItem[1] in ('0', 'G'):
                routeSuffix = updateListItem[3]
            else:
                routeSuffix = '0'
        else:
            routeSuffix = '0'

        lrsDirToUse = ''
        if updateListItem[5] in ('0', '1'):
            lrsDirToUse = str(updateListItem[5])
        elif updateListItem[4] in ('EB', 'NB'):
            lrsDirToUse = '0'
        elif updateListItem[4] in ('WB', 'SB'):
            lrsDirToUse = '1'
        else:
            lrsDirToUse = '0'

        uniqueToUse = ''
        if str(updateListItem[6]).lower() != 'none':
            uniqueToUse = updateListItem[6]
        elif str(updateListItem[8]).lower() != 'none':
            uniqueToUse = updateListItem[8]
        elif str(updateListItem[7]).lower() != 'none':
            uniqueToUse = updateListItem[7]

        if uniqueToUse == '00' and prefixTarget != 'X':
            uniqueToUse = ''
        else:
            pass

        keyToUse = countyPre + prefixTarget + routeNumTarget + routeSuffix + lrsDirToUse + uniqueToUse

        updateListItem[9] = keyToUse
        newCursor.updateRow(updateListItem)

    try:
        del newCursor
    except:
        pass

    # state system only
    # This should be a 8-9 character key, with the last character being a reduced length unique id that's nullable.
    # Prefix (1) + Route number (5) + Suffix (1) + Inventory Direction (1) = 8 characters.
    # Prefix (1) + Route number (5) + Suffix (1) + Inventory Direction (1) + Unique ID (2 reduced to 1) = 9 characters.
    stateSystemSelectionQuery = """ SourceRouteId LIKE '___I%' OR LRS_ROUTE_PREFIX = 'I' OR SourceRouteId LIKE '___U%' OR LRS_ROUTE_PREFIX = 'U' OR SourceRouteId LIKE '___K%' OR LRS_ROUTE_PREFIX = 'K' """
    updateFields = [
        'LRS_COUNTY_PRE', 'ROUTE_PREFIX_TARGET', 'LRS_ROUTE_NUM_TARGET',
        'LRS_ROUTE_SUFFIX', 'LRS_DIRECTION', 'KDOT_DIRECTION_CALC',
        uniqueIdTarget, 'LRS_UNIQUE_IDENT', 'LRS_UNIQUE_IDENT1',
        targetStateLRSKey
    ]

    newCursor = daUpdateCursor(fcToCalculateTargetKeysIn, updateFields,
                               stateSystemSelectionQuery)

    for updateItem in newCursor:
        updateListItem = list(updateItem)
        keyToUse = ''
        #ignore countyPre for state network keys
        countyPre = ''
        '''
        if updateListItem[0] is not None:
            countyPre = updateListItem[0]
        else:
            countyPre = '404' # County Not Found
        '''
        if str(updateListItem[1]).lower() != 'none':
            prefixTarget = updateListItem[1]
        else:
            prefixTarget = '8'  # For 'other'.
        if str(updateListItem[2]).lower() != 'none':
            routeNumTarget = updateListItem[2]
        else:
            routeNumTarget = str('').zfill(5)
        if str(updateListItem[3]).lower() != 'none':
            if int(str(updateListItem[1])) <= 6:
                routeSuffix = updateListItem[3]
            elif updateListItem in ('0', 'G'):
                routeSuffix = updateListItem[3]
            else:
                routeSuffix = '0'
        else:
            routeSuffix = '0'

        lrsDirToUse = ''
        if updateListItem[5] in ('0', '1'):
            lrsDirToUse = str(updateListItem[5])
        elif updateListItem[4] in ('EB', 'NB'):
            lrsDirToUse = '0'
        elif updateListItem[4] in ('WB', 'SB'):
            lrsDirToUse = '1'
        else:
            lrsDirToUse = '0'

        uniqueToUse = ''
        if str(updateListItem[6]).lower() != 'none':
            uniqueToUse = str(updateListItem[6])[-1]
        elif str(updateListItem[8]).lower() != 'none':
            uniqueToUse = str(updateListItem[8])[-1]
        elif str(updateListItem[7]).lower() != 'none':
            uniqueToUse = str(updateListItem[7])[-1]

        if uniqueToUse == '00' and prefixTarget != 'X':
            uniqueToUse = ''
        else:
            pass

        keyToUse = countyPre + prefixTarget + routeNumTarget + routeSuffix + lrsDirToUse + uniqueToUse

        updateListItem[9] = keyToUse
        newCursor.updateRow(updateListItem)

    try:
        del newCursor
    except:
        pass
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 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 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