def createOutput(self, rowStandard = False): """ Write Kernel-based Weights to File. """ ARCPY.SetProgressor("default", \ "Writing Spatial Weights to Output File...") #### Shorthand Attributes #### ssdo = self.ssdo idField = self.idField weightObj = self.weightObj outputFile = self.outputFile outputExt = self.outputExt #### Get File Name Without Extension #### fileName = ssdo.inName.rsplit('.', 1)[0] if outputExt == EXTENSIONS[0]: # KWT file outputWriter = PYSAL.open(outputFile, 'w') outputWriter.shpName = fileName if idField: outputWriter.varName = idField outputWriter.write(weightObj) outputWriter.close() else: # SWM file masterField = idField if idField else 'UNKNOWN' swmWriter = WU.SWMWriter(outputFile, masterField, \ ssdo.spatialRefName, weightObj.n, \ rowStandard) masterIDs = list(weightObj.neighbors.keys()) masterIDs.sort() for key in masterIDs: swmWriter.swm.writeEntry(key, weightObj.neighbors[key], \ weightObj.weights[key]) swmWriter.close()
def createOutput(self, rowStandard=False): """ Write Distance-based Weights to File. """ ARCPY.SetProgressor("default", \ "Writing Spatial Weights to Output File...") #### Shorthand Attributes #### ssdo = self.ssdo idField = self.idField weightObj = self.weightObj outputFile = self.outputFile outputExt = self.outputExt #### Get File Name Without Extension #### fileName = ssdo.inName.rsplit('.', 1)[0] if outputExt == EXTENSIONS[0]: # GAL file outputWriter = open(outputFile, 'w') # write header in the first line header = "%s\n" % weightObj.n if not idField else \ "%s %s %s %s\n" % (0, weightObj.n, idField, 'UNKNOWN') outputWriter.write(header) # write content masterIDs = weightObj.neighbors.keys() masterIDs.sort() for id in masterIDs: neighbors = weightObj.neighbors[id] outputWriter.write("%s %s\n" % (id, len(neighbors))) outputWriter.write("%s\n" % \ (" ".join([str(nbr) for nbr in neighbors]))) outputWriter.close() elif outputExt == EXTENSIONS[1]: # GWT file outputWriter = PYSAL.open(outputFile, 'w') outputWriter.shpName = fileName if idField: outputWriter.varName = idField outputWriter.write(weightObj) outputWriter.close() else: # SWM file masterField = idField if idField else 'UNKNOWN' swmWriter = WU.SWMWriter(outputFile, masterField, \ ssdo.spatialRefName, weightObj.n, \ rowStandard) masterIDs = weightObj.neighbors.keys() masterIDs.sort() for key in masterIDs: swmWriter.swm.writeEntry(key, weightObj.neighbors[key], \ weightObj.weights[key]) swmWriter.close()
def createOutput(self, rowStandard=False): """ Write New Weights File. """ ARCPY.SetProgressor("default", \ "Writing new spatial weights file as output...") #### Shorthand Attributes #### ssdo = self.ssdo weightObj = self.weightObj inputIDField = self.inputIDField outputFile = self.outputFile outputExt = self.outputExt #### Write WeightObj to New Weights File #### uniqueID = weightObj._varName if not uniqueID: uniqueID = inputIDField if outputExt == EXTENSIONS[0]: # GAL file outputWriter = open(outputFile, 'w') header = "%s %s %s %s\n" % \ (0, weightObj.n, uniqueID, 'UNKNOWN') outputWriter.write(header) masterIDs = list(weightObj.neighbors.keys()) masterIDs.sort() for id in masterIDs: neighbors = weightObj.neighbors[id] outputWriter.write("%s %s\n" % (id, len(neighbors))) outputWriter.write("%s\n" % \ (" ".join([str(nbr) for nbr in neighbors]))) outputWriter.close() elif outputExt == EXTENSIONS[1] or outputExt == EXTENSIONS[2]: # GWT, KWT outputWriter = PYSAL.open(outputFile, 'w') outputWriter.varName = uniqueID outputWriter.write(weightObj) outputWriter.close() else: # SWM swmWriter = WU.SWMWriter(outputFile, uniqueID, \ ssdo.spatialRefName if ssdo else '#', \ weightObj.n, rowStandard) masterIDs = weightObj.neighbors.keys() masterIDs.sort() for key in masterIDs: swmWriter.swm.writeEntry(key, weightObj.neighbors[key], \ weightObj.weights[key]) swmWriter.close()
def table2SWM(inputFC, masterField, swmFile, tableFile, rowStandard = True): """Converts a weigths matrix in table format into SWM format. 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. tableFile (str) path to the database table rowStandard {bool, True}: row standardize weights? """ #### Set Default Progressor for Neigborhood Structure #### ARCPY.SetProgressor("default", ARCPY.GetIDMessage(84123)) #### Create SSDataObject #### ssdo = SSDO.SSDataObject(inputFC, templateFC = inputFC) #### Obtain Unique IDs from Input Feature Class #### ssdo.obtainData(masterField, minNumObs = 2) ARCPY.SetProgressor("default", ARCPY.GetIDMessage(84123)) master2Order = ssdo.master2Order allMaster = master2Order.keys() n = ssdo.numObs #### Create Search Cursor for Input Weights Table #### neighFieldName = "NID" weightFieldName = "WEIGHT" fieldList = [masterField, neighFieldName, weightFieldName] try: rows = DA.SearchCursor(tableFile, fieldList) except: ARCPY.AddIDMessage("Error", 722) raise SystemExit() #### Initialize Spatial Weights Matrix File #### swmWriter = WU.SWMWriter(swmFile, masterField, ssdo.spatialRefName, n, rowStandard, inputFC = inputFC, wType = 8, inputTable = tableFile) #### Set Progressor for SWM Reading/Writing #### c = 0 cnt = UTILS.getCount(tableFile) ARCPY.SetProgressor("step", ARCPY.GetIDMessage(84123), 0, cnt, 1) lastID = "NULL" neighs = [] weights = [] #### Process Spatial Weights #### for row in rows: masterID = row[0] if master2Order.has_key(masterID): neighID = row[1] weight = row[2] if masterID == lastID: #### Append to Current Record #### try: testNeigh = master2Order[neighID] neighs.append(neighID) weights.append(weight) except: #### NID Does Not Exist / Not In Selection #### pass #### Set Progress #### ARCPY.SetProgressorPosition() else: #### Create New Record if not NULL #### if lastID != "NULL": allMaster.remove(lastID) swmWriter.swm.writeEntry(lastID, neighs, weights) #### Reset and Initialize Containers #### neighs = [neighID] weights = [weight] else: #### Create First Record #### try: testNeigh = master2Order[neighID] neighs.append(neighID) weights.append(weight) except: #### NID Does Not Exist / Not In Selection #### pass lastID = masterID #### Set Progress #### ARCPY.SetProgressorPosition() else: #### Unique Id Does Not Exist / Not In Selection #### ARCPY.SetProgressorPosition() #### Write Last Record #### swmWriter.swm.writeEntry(lastID, neighs, weights) try: allMaster.remove(lastID) except: pass #### Set Progress #### ARCPY.SetProgressorPosition() #### Write No Neighbor Features #### for masterID in allMaster: swmWriter.swm.writeEntry(masterID, [], []) #### Report Warning/Max Neighbors #### swmWriter.reportNeighInfo() #### Report Spatial Weights Summary #### swmWriter.report() #### Report SWM File is Large #### swmWriter.reportLargeSWM() #### Clean Up #### swmWriter.close() del rows
def spaceTime2SWM(inputFC, swmFile, masterField, concept = "EUCLIDEAN", threshold = None, rowStandard = True, timeField = None, timeType = None, timeValue = None): """ inputFC (str): path to the input feature class swmFile (str): path to the SWM file. masterField (str): field in table that serves as the mapping. concept: {str, EUCLIDEAN}: EUCLIDEAN or MANHATTAN threshold {float, None}: distance threshold rowStandard {bool, True}: row standardize weights? timeField {str, None}: name of the date-time field timeType {str, None}: ESRI enumeration of date-time intervals timeValue {float, None}: value forward and backward in time """ #### Assure Temporal Parameters are Set #### if not timeField: ARCPY.AddIDMessage("ERROR", 1320) raise SystemExit() if not timeType: ARCPY.AddIDMessage("ERROR", 1321) raise SystemExit() if not timeValue or timeValue <= 0: ARCPY.AddIDMessage("ERROR", 1322) raise SystemExit() #### Create SSDataObject #### ssdo = SSDO.SSDataObject(inputFC, templateFC = inputFC, useChordal = True) cnt = UTILS.getCount(inputFC) ERROR.errorNumberOfObs(cnt, minNumObs = 2) ARCPY.SetProgressor("step", ARCPY.GetIDMessage(84001), 0, cnt, 1) #### Validation of Master Field #### verifyMaster = ERROR.checkField(ssdo.allFields, masterField, types = [0,1]) badIDs = [] #### Create Temporal Hash #### timeInfo = {} xyCoords = NUM.empty((cnt, 2), float) #### Process Field Values #### fieldList = [masterField, "SHAPE@XY", timeField] try: rows = DA.SearchCursor(ssdo.catPath, fieldList, "", ssdo.spatialRefString) except: ARCPY.AddIDMessage("ERROR", 204) raise SystemExit() #### Add Data to GATable and Time Dictionary #### c = 0 for row in rows: badRow = False #### Assure Masterfield is Valid #### masterID = row[0] if masterID == None or masterID == "": badRow = True #### Assure Date/Time is Valid #### timeStamp = row[-1] if timeStamp == None or timeStamp == "": badRow = True #### Assure Centroid is Valid #### badXY = row[1].count(None) if not badXY: x,y = row[1] xyCoords[c] = (x,y) else: badRow = True #### Process Data #### if not badRow: if timeInfo.has_key(masterID): #### Assure Uniqueness #### ARCPY.AddIDMessage("Error", 644, masterField) ARCPY.AddIDMessage("Error", 643) raise SystemExit() else: #### Fill Date/Time Dict #### startDT, endDT = TUTILS.calculateTimeWindow(timeStamp, timeValue, timeType) timeInfo[masterID] = (timeStamp, startDT, endDT) else: badIDs.append(masterID) #### Set Progress #### c += 1 ARCPY.SetProgressorPosition() #### Clean Up #### del rows #### Get Set of Bad IDs #### numBadObs = len(badIDs) badIDs = list(set(badIDs)) badIDs.sort() badIDs = [ str(i) for i in badIDs ] #### Process any bad records encountered #### if numBadObs: ERROR.reportBadRecords(cnt, numBadObs, badIDs, label = masterField) #### Load Neighbor Table #### gaTable, gaInfo = WU.gaTable(ssdo.inputFC, fieldNames = [masterField, timeField], spatRef = ssdo.spatialRefString) numObs = len(gaTable) xyCoords = xyCoords[0:numObs] #### Set the Distance Threshold #### concept, gaConcept = WU.validateDistanceMethod(concept, ssdo.spatialRef) if threshold == None: #### Set Progressor for Search #### ARCPY.SetProgressor("default", ARCPY.GetIDMessage(84144)) #### Create k-Nearest Neighbor Search Type #### gaSearch = GAPY.ga_nsearch(gaTable) gaSearch.init_nearest(0.0, 1, gaConcept) neighDist = ARC._ss.NeighborDistances(gaTable, gaSearch) N = len(neighDist) threshold = 0.0 sumDist = 0.0 #### Find Maximum Nearest Neighbor Distance #### for row in xrange(N): dij = neighDist[row][-1][0] if dij > threshold: threshold = dij sumDist += dij ARCPY.SetProgressorPosition() #### Increase For Rounding Error #### threshold = threshold * 1.0001 avgDist = sumDist / (N * 1.0) #### Add Linear/Angular Units #### thresholdStr = ssdo.distanceInfo.printDistance(threshold) ARCPY.AddIDMessage("Warning", 853, thresholdStr) #### Chordal Default Check #### if ssdo.useChordal: hardMaxExtent = ARC._ss.get_max_gcs_distance(ssdo.spatialRef) if threshold > hardMaxExtent: ARCPY.AddIDMessage("ERROR", 1609) raise SystemExit() #### Clean Up #### del gaSearch #### Create Missing SSDO Info #### extent = UTILS.resetExtent(xyCoords) #### Reset Coordinates for Chordal #### if ssdo.useChordal: sliceInfo = UTILS.SpheroidSlice(extent, ssdo.spatialRef) maxExtent = sliceInfo.maxExtent else: env = UTILS.Envelope(extent) maxExtent = env.maxExtent threshold = checkDistanceThresholdSWM(ssdo, threshold, maxExtent) #### Set Default Progressor for Neigborhood Structure #### ARCPY.SetProgressor("default", ARCPY.GetIDMessage(84143)) #### Create Distance Neighbor Search Type #### gaSearch = GAPY.ga_nsearch(gaTable) gaSearch.init_nearest(threshold, 0, gaConcept) neighSearch = ARC._ss.NeighborSearch(gaTable, gaSearch) #### Set Progressor for Weights Writing #### ARCPY.SetProgressor("step", ARCPY.GetIDMessage(84127), 0, numObs, 1) #### Initialize Spatial Weights Matrix File #### swmWriter = WU.SWMWriter(swmFile, masterField, ssdo.spatialRefName, numObs, rowStandard, inputFC = inputFC, wType = 9, distanceMethod = concept, threshold = threshold, timeField = timeField, timeType = timeType, timeValue = timeValue) for row in xrange(numObs): masterID = gaTable[row][2] #### Get Date/Time Info #### dt0, startDT0, endDT0 = timeInfo[masterID] nhs = neighSearch[row] neighs = [] weights = [] for nh in nhs: #### Search Through Spatial Neighbors #### neighID = gaTable[nh][2] #### Get Date/Time Info #### dt1, startDT1, endDT1 = timeInfo[neighID] #### Filter Based on Date/Time #### insideTimeWindow = TUTILS.isTimeNeighbor(startDT0, endDT0, dt1) if insideTimeWindow: neighs.append(neighID) weights.append(1.0) #### Add Spatial Weights Matrix Entry #### swmWriter.swm.writeEntry(masterID, neighs, weights) #### Set Progress #### ARCPY.SetProgressorPosition() swmWriter.close() del gaTable #### Report Warning/Max Neighbors #### swmWriter.reportNeighInfo() #### Report Spatial Weights Summary #### swmWriter.report() #### Report SWM File is Large #### swmWriter.reportLargeSWM()
def distance2SWM(inputFC, swmFile, masterField, fixed = 0, concept = "EUCLIDEAN", exponent = 1.0, threshold = None, kNeighs = 1, rowStandard = True): """Creates a sparse spatial weights matrix (SWM) based on k-nearest neighbors. INPUTS: inputFC (str): path to the input feature class swmFile (str): path to the SWM file. masterField (str): field in table that serves as the mapping. fixed (boolean): fixed (1) or inverse (0) distance? concept: {str, EUCLIDEAN}: EUCLIDEAN or MANHATTAN exponent {float, 1.0}: distance decay threshold {float, None}: distance threshold kNeighs (int): number of neighbors to return rowStandard {bool, True}: row standardize weights? """ #### Create SSDataObject #### ssdo = SSDO.SSDataObject(inputFC, templateFC = inputFC, useChordal = True) #### Validation of Master Field #### verifyMaster = ERROR.checkField(ssdo.allFields, masterField, types = [0,1]) #### Read Data #### ssdo.obtainDataGA(masterField, minNumObs = 2) N = ssdo.numObs gaTable = ssdo.gaTable if fixed: wType = 1 else: wType = 0 #### Set Default Progressor for Neigborhood Structure #### ARCPY.SetProgressor("default", ARCPY.GetIDMessage(84143)) #### Set the Distance Threshold #### concept, gaConcept = WU.validateDistanceMethod(concept, ssdo.spatialRef) if threshold == None: threshold, avgDist = WU.createThresholdDist(ssdo, concept = concept) #### Assures that the Threshold is Appropriate #### gaExtent = UTILS.get92Extent(ssdo.extent) threshold, maxSet = WU.checkDistanceThreshold(ssdo, threshold, weightType = wType) #### If the Threshold is Set to the Max #### #### Set to Zero for Script Logic #### if maxSet: #### All Locations are Related #### threshold = SYS.maxint if N > 500: ARCPY.AddIDMessage("Warning", 717) #### Assure k-Nearest is Less Than Number of Features #### if kNeighs >= N and fixed: ARCPY.AddIDMessage("ERROR", 975) raise SystemExit() #### Create Distance/k-Nearest Neighbor Search Type #### gaSearch = GAPY.ga_nsearch(gaTable) gaSearch.init_nearest(threshold, kNeighs, gaConcept) neighWeights = ARC._ss.NeighborWeights(gaTable, gaSearch, weight_type = wType, exponent = exponent, row_standard = False) #### Set Progressor for Weights Writing #### ARCPY.SetProgressor("step", ARCPY.GetIDMessage(84127), 0, N, 1) #### Initialize Spatial Weights Matrix File #### swmWriter = WU.SWMWriter(swmFile, masterField, ssdo.spatialRefName, N, rowStandard, inputFC = inputFC, wType = wType, distanceMethod = concept, exponent = exponent, threshold = threshold) #### Unique Master ID Dictionary #### masterDict = {} #### Unique Master ID Dictionary #### masterSet = set([]) for row in xrange(N): masterID = int(gaTable[row][2]) if masterID in masterSet: ARCPY.AddIDMessage("Error", 644, masterField) ARCPY.AddIDMessage("Error", 643) raise SystemExit() else: masterSet.add(masterID) neighs, weights = neighWeights[row] neighs = [ gaTable[nh][2] for nh in neighs ] #### Add Spatial Weights Matrix Entry #### swmWriter.swm.writeEntry(masterID, neighs, weights) #### Set Progress #### ARCPY.SetProgressorPosition() swmWriter.close() del gaTable #### Report Warning/Max Neighbors #### swmWriter.reportNeighInfo() #### Add Linear/Angular Unit (Distance Based Only) #### distanceOut = ssdo.distanceInfo.outputString distanceOut = [ARCPY.GetIDMessage(84344).format(distanceOut)] #### Report Spatial Weights Summary #### swmWriter.report(additionalInfo = distanceOut) #### Report SWM File is Large #### swmWriter.reportLargeSWM()
def kNearest2SWM(inputFC, swmFile, masterField, concept = "EUCLIDEAN", kNeighs = 1, rowStandard = True): """Creates a sparse spatial weights matrix (SWM) based on k-nearest neighbors. INPUTS: inputFC (str): path to the input feature class swmFile (str): path to the SWM file. masterField (str): field in table that serves as the mapping. concept: {str, EUCLIDEAN}: EUCLIDEAN or MANHATTAN kNeighs {int, 1}: number of neighbors to return rowStandard {bool, True}: row standardize weights? """ #### Assure that kNeighs is Non-Zero #### if kNeighs <= 0: ARCPY.AddIDMessage("ERROR", 976) raise SystemExit() #### Set Default Progressor for Neigborhood Structure #### ARCPY.SetProgressor("default", ARCPY.GetIDMessage(84143)) #### Create SSDataObject #### ssdo = SSDO.SSDataObject(inputFC, templateFC = inputFC, useChordal = True) cnt = UTILS.getCount(inputFC) ERROR.errorNumberOfObs(cnt, minNumObs = 2) #### Validation of Master Field #### verifyMaster = ERROR.checkField(ssdo.allFields, masterField, types = [0,1]) #### Create GA Data Structure #### gaTable, gaInfo = WU.gaTable(ssdo.catPath, [masterField], spatRef = ssdo.spatialRefString) #### Assure Enough Observations #### N = gaInfo[0] ERROR.errorNumberOfObs(N, minNumObs = 2) #### Process any bad records encountered #### numBadRecs = cnt - N if numBadRecs: badRecs = WU.parseGAWarnings(gaTable.warnings) err = ERROR.reportBadRecords(cnt, numBadRecs, badRecs, label = ssdo.oidName) #### Assure k-Nearest is Less Than Number of Features #### if kNeighs >= N: ARCPY.AddIDMessage("ERROR", 975) raise SystemExit() #### Create k-Nearest Neighbor Search Type #### gaSearch = GAPY.ga_nsearch(gaTable) concept, gaConcept = WU.validateDistanceMethod(concept, ssdo.spatialRef) gaSearch.init_nearest(0.0, kNeighs, gaConcept) neighWeights = ARC._ss.NeighborWeights(gaTable, gaSearch, weight_type = 1, row_standard = False) #### Set Progressor for Weights Writing #### ARCPY.SetProgressor("step", ARCPY.GetIDMessage(84127), 0, N, 1) #### Initialize Spatial Weights Matrix File #### swmWriter = WU.SWMWriter(swmFile, masterField, ssdo.spatialRefName, N, rowStandard, inputFC = inputFC, wType = 2, distanceMethod = concept, numNeighs = kNeighs) #### Unique Master ID Dictionary #### masterSet = set([]) for row in xrange(N): masterID = int(gaTable[row][2]) if masterID in masterSet: ARCPY.AddIDMessage("Error", 644, masterField) ARCPY.AddIDMessage("Error", 643) raise SystemExit() else: masterSet.add(masterID) neighs, weights = neighWeights[row] neighs = [ gaTable[nh][2] for nh in neighs ] #### Add Spatial Weights Matrix Entry #### swmWriter.swm.writeEntry(masterID, neighs, weights) #### Set Progress #### ARCPY.SetProgressorPosition() swmWriter.close() del gaTable #### Report Warning/Max Neighbors #### swmWriter.reportNeighInfo() #### Report Spatial Weights Summary #### swmWriter.report() #### Report SWM File is Large #### swmWriter.reportLargeSWM()
def delaunay2SWM(inputFC, swmFile, masterField, rowStandard = True): """Creates a sparse spatial weights matrix (SWM) based on Delaunay Triangulation. INPUTS: inputFC (str): path to the input feature class swmFile (str): path to the SWM file. masterField (str): field in table that serves as the mapping. rowStandard {bool, True}: row standardize weights? """ #### Set Default Progressor for Neigborhood Structure #### ARCPY.SetProgressor("default", ARCPY.GetIDMessage(84143)) #### Create SSDataObject #### ssdo = SSDO.SSDataObject(inputFC, templateFC = inputFC, useChordal = True) cnt = UTILS.getCount(inputFC) ERROR.errorNumberOfObs(cnt, minNumObs = 2) #### Validation of Master Field #### verifyMaster = ERROR.checkField(ssdo.allFields, masterField, types = [0,1]) #### Create GA Data Structure #### gaTable, gaInfo = WU.gaTable(ssdo.catPath, [masterField], spatRef = ssdo.spatialRefString) #### Assure Enough Observations #### N = gaInfo[0] ERROR.errorNumberOfObs(N, minNumObs = 2) #### Process any bad records encountered #### numBadRecs = cnt - N if numBadRecs: badRecs = WU.parseGAWarnings(gaTable.warnings) err = ERROR.reportBadRecords(cnt, numBadRecs, badRecs, label = ssdo.oidName) #### Create Delaunay Neighbor Search Type #### gaSearch = GAPY.ga_nsearch(gaTable) gaSearch.init_delaunay() neighWeights = ARC._ss.NeighborWeights(gaTable, gaSearch, weight_type = 1, row_standard = False) #### Set Progressor for Weights Writing #### ARCPY.SetProgressor("step", ARCPY.GetIDMessage(84127), 0, N, 1) #### Initialize Spatial Weights Matrix File #### swmWriter = WU.SWMWriter(swmFile, masterField, ssdo.spatialRefName, N, rowStandard, inputFC = inputFC, wType = 3) #### Unique Master ID Dictionary #### masterSet = set([]) for row in xrange(N): masterID = int(gaTable[row][2]) if masterID in masterSet: ARCPY.AddIDMessage("Error", 644, masterField) ARCPY.AddIDMessage("Error", 643) raise SystemExit() else: masterSet.add(masterID) neighs, weights = neighWeights[row] neighs = [ gaTable[nh][2] for nh in neighs ] #### Add Spatial Weights Matrix Entry #### swmWriter.swm.writeEntry(masterID, neighs, weights) #### Set Progress #### ARCPY.SetProgressorPosition() #### Clean Up #### swmWriter.close() del gaTable #### Report if Any Features Have No Neighbors #### swmWriter.reportNoNeighbors() #### Report Spatial Weights Summary #### swmWriter.report() #### Report SWM File is Large #### swmWriter.reportLargeSWM()
def polygon2SWM(inputFC, swmFile, masterField, concept = "EUCLIDEAN", kNeighs = 0, rowStandard = True, contiguityType = "ROOK"): """Creates a sparse spatial weights matrix (SWM) based on polygon contiguity. INPUTS: inputFC (str): path to the input feature class swmFile (str): path to the SWM file. masterField (str): field in table that serves as the mapping. concept: {str, EUCLIDEAN}: EUCLIDEAN or MANHATTAN kNeighs {int, 0}: number of neighbors to return (1) rowStandard {bool, True}: row standardize weights? contiguityType {str, Rook}: {Rook = Edges Only, Queen = Edges/Vertices} NOTES: (1) kNeighs is used if polygon is not contiguous. E.g. Islands """ #### Set Default Progressor for Neigborhood Structure #### ARCPY.SetProgressor("default", ARCPY.GetIDMessage(84143)) #### Create SSDataObject #### ssdo = SSDO.SSDataObject(inputFC, templateFC = inputFC, useChordal = True) cnt = UTILS.getCount(inputFC) ERROR.errorNumberOfObs(cnt, minNumObs = 2) #### Validation of Master Field #### verifyMaster = ERROR.checkField(ssdo.allFields, masterField, types = [0,1]) #### Create GA Data Structure #### gaTable, gaInfo = WU.gaTable(ssdo.catPath, [masterField], spatRef = ssdo.spatialRefString) #### Assure Enough Observations #### N = gaInfo[0] ERROR.errorNumberOfObs(N, minNumObs = 2) #### Assure k-Nearest is Less Than Number of Features #### if kNeighs >= N: ARCPY.AddIDMessage("ERROR", 975) raise SystemExit() #### Create Nearest Neighbor Search Type For Islands #### gaSearch = GAPY.ga_nsearch(gaTable) concept, gaConcept = WU.validateDistanceMethod(concept, ssdo.spatialRef) gaSearch.init_nearest(0.0, kNeighs, gaConcept) if kNeighs > 0: forceNeighbor = True neighWeights = ARC._ss.NeighborWeights(gaTable, gaSearch, weight_type = 1, row_standard = False) else: forceNeighbor = False neighSearch = None #### Create Polygon Neighbors #### polyNeighborDict = WU.polygonNeighborDict(inputFC, masterField, contiguityType = contiguityType) #### Write Poly Neighbor List (Dict) #### #### Set Progressor for SWM Writing #### ARCPY.SetProgressor("step", ARCPY.GetIDMessage(84127), 0, N, 1) #### Initialize Spatial Weights Matrix File #### if contiguityType == "ROOK": wType = 4 else: wType = 5 swmWriter = WU.SWMWriter(swmFile, masterField, ssdo.spatialRefName, N, rowStandard, inputFC = inputFC, wType = wType, distanceMethod = concept, numNeighs = kNeighs) #### Keep Track of Polygons w/o Neighbors #### islandPolys = [] #### Write Polygon Contiguity to SWM File #### for row in xrange(N): rowInfo = gaTable[row] oid = rowInfo[0] masterID = rowInfo[2] neighs = polyNeighborDict[masterID] if neighs: weights = [ 1. for nh in neighs ] isIsland = False else: isIsland = True islandPolys.append(oid) weights = [] #### Get Nearest Neighbor Based On Centroid Distance #### if isIsland and forceNeighbor: neighs, weights = neighWeights[row] neighs = [ gaTable[nh][2] for nh in neighs ] #### Add Weights Entry #### swmWriter.swm.writeEntry(masterID, neighs, weights) #### Set Progress #### ARCPY.SetProgressorPosition() #### Report on Features with No Neighbors #### countIslands = len(islandPolys) if countIslands: islandPolys.sort() if countIslands > 30: islandPolys = islandPolys[0:30] ERROR.warningNoNeighbors(N, countIslands, islandPolys, ssdo.oidName, forceNeighbor = forceNeighbor, contiguity = True) #### Clean Up #### swmWriter.close() del gaTable #### Report Spatial Weights Summary #### swmWriter.report() #### Report SWM File is Large #### swmWriter.reportLargeSWM() del polyNeighborDict
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()