def network2SWM(inputFC, masterField, swmFile, inputNetwork, impedance, cutoff = "#", numberOfNeighs = "#", inputBarrier = "#", uturnPolicy = "ALLOW_UTURNS", restrictions = "#", hierarchy = 'NO_HIERARCHY', searchTolerance = "#", fixed = 0, exponent = 1.0, rowStandard = True): """Creates spatial weights in SWM format from a combination of network data and feature classes. INPUTS: inputFC (str): path to the input feature class masterField (str): field in table that serves as the mapping swmFile (str): path to the SWM file inputNetwork (str): path to the network dataset (*.nd) impedance (str): attribute from network dataset (1) cutoff {float, "#"}: impedance threshold numberOfNeighs {int, "#"}: number of neighbors to return inputBarrier {str, "#"}: path to the input barrier feature class uturnPolicy {str, ALLOW_UTURNS}: uturn policy (2) restrictions {str, "#"}: attribute from network dataset (3) hierarchy {str, NO_HIERARCHY}: NO_HIERARCHY or USE_HIERARCHY searchTolerance {linear measure, "#"}: snap tolerance for network (4) fixed {int, 0}: Invert impedance as weight or return a weight = 1? exponent {float, 1.0}: distance decay rowStandard {bool, True}: row standardize weights? NOTES: (1) E.g. MINUTES and METERS (2) E.g. ALLOW_UTURNS or NO_UTURNS (3) E.g. ONEWAY (4) E.g. 5000 METERS """ #### Check out Network Analyst #### try: ARCPY.CheckOutExtension("Network") except: ARCPY.AddIDMessage("ERROR", 849) raise SystemExit() #### OD Matrix and Layers #### ODCostMatrix = "ODMatrix" BarriersLayerNames = {"POINT": 'Barriers', "POLYLINE" : 'PolylineBarriers', "LINE" : 'PolylineBarriers', "POLYGON" : 'PolygonBarriers'} lines = ODCostMatrix + "\\Lines" destFCLayer = "NetSWM_Dest" ##### Delete Layers If They Exist #### cleanupNetLayer(ODCostMatrix) cleanupNetLayer(destFCLayer) cleanupNetLayer(lines) #### Get Master Field From inputFC #### ssdo = SSDO.SSDataObject(inputFC, useChordal = False) ssdo.obtainDataGA(masterField, minNumObs = 2) master2Order = ssdo.master2Order masterFieldObj = ssdo.allFields[masterField.upper()] allMaster = master2Order.keys() numObs = ssdo.numObs numPossNeighs = numObs - 1 #### Get Spatial Ref From Net Data Set #### netDesc = ARCPY.Describe(inputNetwork) netSpatialRef = netDesc.SpatialReference netSpatName = netSpatialRef.Name #### Set Maximum Neighbor Argument #### if numberOfNeighs == "#": numberOfNeighs = min( [numPossNeighs, 30] ) ARCPY.AddIDMessage("WARNING", 1012, numberOfNeighs) if numberOfNeighs >= numObs: numberOfNeighs = numPossNeighs ARCPY.AddIDMessage("WARNING", 1013, numberOfNeighs) if numberOfNeighs == 0: numberOfNeighs = numPossNeighs #### All Features are Related. Force Inverse Impedance #### if (numObs - numberOfNeighs) <= 1: if fixed: ARCPY.AddIDMessage("WARNING", 974) fixed = 0 #### Add Self Neighbor For OD Solve #### numberOfNeighsOD = numberOfNeighs + 1 #### Make OD Cost Matrix Layer #### ARCPY.SetProgressor("default", ARCPY.GetIDMessage(84132)) odCostMatrixLayer = NET.MakeODCostMatrixLayer(inputNetwork, ODCostMatrix, impedance, cutoff, numberOfNeighsOD, "#", uturnPolicy, restrictions, hierarchy, "#", "NO_LINES").getOutput(0) #### OD Matrix and Layers #### naClassNames = NET.GetNAClassNames(odCostMatrixLayer) destinationLayer = ODCostMatrix + OS.sep + naClassNames["Destinations"] originLayer = ODCostMatrix + OS.sep + naClassNames["Origins"] lines = ODCostMatrix + OS.sep + naClassNames["ODLines"] #### Add Barriers #### if inputBarrier != "" and inputBarrier != "#": ARCPY.SetProgressor("default", ARCPY.GetIDMessage(84147)) barDesc = ARCPY.Describe(inputBarrier) barShapeType = barDesc.ShapeType.upper() if barShapeType in BarriersLayerNames: barString = naClassNames[BarriersLayerNames[barShapeType]] NET.AddLocations(ODCostMatrix, barString, inputBarrier, "", searchTolerance) #### Add Master Field to OD for Selection #### masterType = UTILS.convertType[masterFieldObj.type] NET.AddFieldToAnalysisLayer(ODCostMatrix, naClassNames["Destinations"], masterField, masterType) #### Add Destinations #### ARCPY.SetProgressor("default", ARCPY.GetIDMessage(84133)) masterToken = "Name " + masterField + " #;" masterToken += masterField + " " + masterField + " #" NET.AddLocations(ODCostMatrix, naClassNames["Destinations"], inputFC, masterToken, searchTolerance, exclude_restricted_elements = "EXCLUDE") #### Initialize Spatial Weights Matrix File #### hierarchyBool = hierarchy == 'USE_HIERARCHY' addConcept = WU.wTypeDispatch[fixed].split("_")[0] forceFixed = (fixed == True) swmWriter = WU.SWMWriter(swmFile, masterField, netSpatName, numObs, rowStandard, inputFC = inputFC, wType = 10, inputNet = inputNetwork, impedanceField = impedance, barrierFC = inputBarrier, uturnPolicy = uturnPolicy, restrictions = restrictions, useHierarchy = hierarchyBool, searchTolerance = searchTolerance, addConcept = addConcept, exponent = exponent, forceFixed = forceFixed) #### Create FieldList for Subset Searching #### totalImpedance = "Total_" + impedance fieldList = ";".join( ["NAME", totalImpedance] ) #### Get Chunks if Necessary #### numOrigins = int(10000000. / numObs) allMaster.sort() chunkedIDs = UTILS.chunk(allMaster, numOrigins) sqlStrings = UTILS.sqlChunkStrings(inputFC, masterField, chunkedIDs) numChunks = len(sqlStrings) #### Create Field Map for Origins #### masterToken = "Name " + masterField + " #" orgFieldMap = [masterToken, 'CurbApproach CurbApproach 0', 'SourceID SourceID #', 'SourceOID SourceOID #', 'PosAlong PosAlong #', 'SideOfEdge SideOfEdge #'] orgFieldMap = ";".join(orgFieldMap) #### Keep Track of Features That Snap to Network #### snappedFeatures = set([]) for chunkNum in xrange(numChunks): progMsg = ARCPY.GetIDMessage(84145).format(chunkNum + 1, numChunks) ARCPY.SetProgressor("default", progMsg) #### Make Origins from Chunk of Destinations #### sqlValue = sqlStrings[chunkNum] DM.MakeFeatureLayer(destinationLayer, destFCLayer, sqlValue) NET.AddLocations(ODCostMatrix, naClassNames["Origins"], destFCLayer, orgFieldMap, "#", "#", "#", "#", "CLEAR") #### Solve OD Matrix and Select Data #### NET.Solve(ODCostMatrix, "SKIP") #### Count the Number of NonZero Spatial Linkages #### numLinks = UTILS.getCount(lines) #### Create Search Cursor for OD Line Info #### rows = ARCPY.SearchCursor(lines, "", None, fieldList) row = rows.next() #### Set Tool Progressor and Process Information #### ARCPY.SetProgressor("step", ARCPY.GetIDMessage(84127), 0, numLinks, 1) #### Process First Record #### ODInfo = row.getValue("NAME") lastID, neighID = [ int(i) for i in ODInfo.split(" - ") ] impValue = row.getValue(totalImpedance) weight = WU.distance2Weight(impValue, wType = fixed, exponent = exponent) neighs = [] weights = [] if lastID != neighID: neighs.append(neighID) weights.append(weight) #### Process Remaining Records #### progMsg = ARCPY.GetIDMessage(84146).format(chunkNum + 1, numChunks) ARCPY.SetProgressor("step", progMsg, 0, numLinks, 1) while row: #### Get Origin and Destination Unique IDs #### ODInfo = row.getValue("NAME") masterID, neighID = [ int(i) for i in ODInfo.split(" - ") ] #### Obtain Impedance and Create Weight #### impValue = row.getValue(totalImpedance) weight = WU.distance2Weight(impValue, wType = fixed, exponent = exponent) #### Check Whether it is the Same ID #### if masterID == lastID: if masterID != neighID: neighs.append(neighID) weights.append(weight) else: #### New ID, Add Last ID Result to SWM File #### swmWriter.swm.writeEntry(lastID, neighs, weights) snappedFeatures.add(lastID) #### Reset and Initialize Containers #### neighs = [] weights = [] if masterID != neighID: neighs.append(neighID) weights.append(weight) lastID = masterID ARCPY.SetProgressorPosition() row = rows.next() #### Write Last ID Result #### swmWriter.swm.writeEntry(lastID, neighs, weights) snappedFeatures.add(lastID) #### Clean Up #### del rows ##### Delete Layers If They Exist #### cleanupNetLayer(ODCostMatrix) cleanupNetLayer(destFCLayer) cleanupNetLayer(lines) #### Add Empty SWM Entries for Features Not Snapped to Network #### notSnapped = snappedFeatures.symmetric_difference(allMaster) for masterID in notSnapped: swmWriter.swm.writeEntry(masterID, [], []) #### Report Warning/Max Neighbors #### swmWriter.reportNeighInfo() #### Clean Up #### swmWriter.close() #### Report Spatial Weights Summary #### swmWriter.report() #### Report SWM File is Large #### swmWriter.reportLargeSWM()