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 initialize(self): """Populates the instance of the Spatial Statistics Data Object (SSDataObject) and resolves a default distance threshold if none given. """ #### Shorthand Attributes #### ssdo = self.ssdo varName = self.varName self.master2Order = ssdo.master2Order masterField = ssdo.masterField concept = self.concept #### Populate SSDO with Data #### field = ssdo.fields[varName] self.y = field.returnDouble() self.numObs = ssdo.numObs gaExtent = UTILS.get92Extent(ssdo.extent) #### Set Envelope or Slice #### if ssdo.useChordal: softMaxExtent = ssdo.sliceInfo.maxExtent hardMaxExtent = ARC._ss.get_max_gcs_distance(ssdo.spatialRef) maxExtent = min(softMaxExtent, hardMaxExtent) else: env = UTILS.Envelope(ssdo.extent) maxExtent = env.maxExtent #### Set Maximum Distance Allowed #### extentBool = (self.begDist != None) or (self.dIncrement != None) or ssdo.useChordal if extentBool: #### If User Provides Either Input, Set to 75% Max Extent #### self.maxDistance = maxExtent * 0.75 self.allDefaults = False else: #### Set to Diameter of Standard Distance #### self.maxDistance = UTILS.standardDistanceCutoff(ssdo.xyCoords) self.allDefaults = True minimumRadius = (maxExtent * .001) #### Determine Starting Distance #### if self.begDist != None and self.begDist > self.maxDistance: ARCPY.AddIDMessage("WARNING", 929) self.begDist = None self.calculatedBegDist = self.begDist == None self.calculatedIncDist = self.dIncrement == None if self.calculatedBegDist or self.calculatedIncDist: outlierInfo = UTILS.LocationInfo(ssdo, concept = self.concept, stdDeviations = self.stdDeviations, includeCoincident = self.includeCoincident, silentThreshold = True) threshold = outlierInfo.threshold avgDist = outlierInfo.avgDist if self.begDist == None: self.begDist = threshold if self.dIncrement == None: self.dIncrement = avgDist #### Negative Values Not Valid #### if self.begDist < 0: ARCPY.AddIDMessage("ERROR", 933) raise SystemExit() #### Beginning Distance is too Small #### if self.begDist < minimumRadius: ARCPY.AddIDMessage("ERROR", 897, self.begDist) raise SystemExit() #### Determine All Distance Cutoffs #### cutoffs = UTILS.createCutoffsStep(self.begDist, self.dIncrement, self.nIncrements) #### Check Cutoff Values ### countMaxSet = (cutoffs > self.maxDistance).sum() if countMaxSet: #### Throw Warning if ANY Distances Larger than Max Extent #### if (not self.calculatedBegDist) and (not self.calculatedIncDist): ARCPY.AddIDMessage("WARNING", 1285, countMaxSet, self.nIncrements) cutoffs = UTILS.createCutoffsMaxDist(self.begDist, self.maxDistance, self.nIncrements) self.dIncrement = cutoffs[1] - cutoffs[0] #### Print Threshold Distance #### stepMax = cutoffs[-1] thresholdStr = ssdo.distanceInfo.printDistance(self.begDist) threshBool = self.calculatedBegDist if threshBool and not self.silent: ARCPY.AddIDMessage("WARNING", 853, thresholdStr) if self.begDist > (maxExtent * 0.51) \ and not self.calculatedBegDist: ARCPY.AddIDMessage("WARNING", 934) elif stepMax > maxExtent \ and not self.calculatedIncDist: ARCPY.AddIDMessage("WARNING", 935) #### Create Results Labels and Field Names #### resLabels = [ARCPY.GetIDMessage(84179), ARCPY.GetIDMessage(84148), ARCPY.GetIDMessage(84149), ARCPY.GetIDMessage(84150), ARCPY.GetIDMessage(84151), ARCPY.GetIDMessage(84152)] self.resLabels = [ i.replace(":", "").strip() for i in resLabels ] #### Set Attributes #### self.stepMax = stepMax self.cutoffs = NUM.array(cutoffs) self.reverseOrder = range(self.nIncrements - 1, -1, -1) self.cutoffOrder = range(self.nIncrements) self.largestDistBand = self.cutoffs[-1]
def initialize(self): """Reads data into a GA structure for neighborhood searching and sets the study area envelope.""" #### Shorthand Attributes #### ssdo = self.ssdo weightField = self.weightField if weightField: fieldList = [weightField] else: fieldList = [] #### Create GA Data Structure #### ssdo.obtainDataGA(ssdo.oidName, fieldList, minNumObs = 3, warnNumObs = 30) N = len(ssdo.gaTable) #### Get Weights #### if weightField: weights = ssdo.fields[weightField].returnDouble() #### Report No Weights #### weightSum = weights.sum() if not weightSum > 0.0: ARCPY.AddIDMessage("ERROR", 898) raise SystemExit() #### Set Study Area #### ARCPY.SetProgressor("default", ARCPY.GetIDMessage(84248)) clearedMinBoundGeom = UTILS.clearExtent(UTILS.minBoundGeomPoints) #### Set Initial Study Area FC #### if self.studyAreaMethod == 1 and self.studyAreaFC: #### Assure Only A Single Polygon in Study Area FC #### polyCount = UTILS.getCount(self.studyAreaFC) if polyCount != 1: ARCPY.AddIDMessage("ERROR", 936) raise SystemExit() self.tempStudyArea = False #### Read User Provided Study Area #### polyInfo = UTILS.returnPolygon(self.studyAreaFC, spatialRef = ssdo.spatialRefString) self.studyAreaPoly, self.studyArea = polyInfo #### Create Temp Min. Enc. Rectangle and Class #### tempMBG_FC = UTILS.returnScratchName("tempMBG_FC") clearedMinBoundGeom(self.studyAreaPoly, tempMBG_FC, geomType = "RECTANGLE_BY_AREA", spatialRef = ssdo.spatialRef) self.minRect = UTILS.MinRect(tempMBG_FC) UTILS.passiveDelete(tempMBG_FC) else: #### Create Min. Enc. Rectangle #### self.studyAreaFC = UTILS.returnScratchName("regularBound_FC") self.tempStudyArea = True clearedMinBoundGeom(ssdo.xyCoords, self.studyAreaFC, geomType = "RECTANGLE_BY_AREA", spatialRef = ssdo.spatialRef) polyInfo = UTILS.returnPolygon(self.studyAreaFC, spatialRef = ssdo.spatialRefString) self.studyAreaPoly, self.studyArea = polyInfo #### Create Min. Enc. Rectangle Class #### self.minRect = UTILS.MinRect(self.studyAreaFC) if self.reduce: #### Only Need To Create FC if Reduce Buffer #### UTILS.createPolygonFC(self.studyAreaFC, self.studyAreaPoly, spatialRef = ssdo.spatialRefString) #### Set Extent and Envelope and Min Rect #### self.envelope = UTILS.Envelope(ssdo.extent) self.maxDistance = self.minRect.maxLength * 0.25 if self.maxDistance > (self.minRect.minLength * .5): #### 25% of Max Extent is Larger Than Half Min Extent #### #### Results in Reduced Study Area Failure #### if self.reduce: self.maxDistance = self.minRect.minLength * 0.25 #### Determine Distance Increment #### if not self.dIncrement: if self.begDist: distRange = self.maxDistance - self.begDist else: distRange = self.maxDistance self.dIncrement = float(distRange / self.nIncrements) #### Determine Starting Distance #### if not self.begDist: self.begDist = self.dIncrement #### Determine All Distance Cutoffs #### rangeInc = xrange(self.nIncrements) cutoffs = [] for inc in rangeInc: val = (inc * self.dIncrement) + self.begDist cutoffs.append(val) stepMax = cutoffs[-1] #### Check Cutoff Values ### if self.begDist > (self.minRect.maxLength * 0.51): ARCPY.AddIDMessage("WARNING", 934) elif stepMax > self.minRect.maxLength: ARCPY.AddIDMessage("WARNING", 935) #### Set Step Attributes #### self.stepMax = stepMax self.cutoffs = NUM.array(cutoffs) self.reverseOrder = range(self.nIncrements - 1, -1, -1) self.cutoffOrder = range(self.nIncrements) self.largestDistBand = self.cutoffs[-1] self.tolerance = self.minRect.tolerance self.xyTolerance = ssdo.spatialRef.XYTolerance #### Get Linear Unit for Reduce, Simulate and Ripley #### floatMax = self.stepMax * 1.0 self.simulateUnitStr = ssdo.distanceInfo.linearUnitString(floatMax, convert = True) self.reduceUnitStr = "-" + self.simulateUnitStr #### Create Smaller Poly FC for Reduce #### if self.reduce: self.reducedFC = UTILS.returnScratchName("reducedBound_FC") if UTILS.compareFloat(floatMax, 0): ARCPY.AddIDMessage("ERROR", 1170) raise SystemExit() ANA.Buffer(self.studyAreaFC, self.reducedFC, self.reduceUnitStr) reduceInfo = UTILS.returnPolygon(self.reducedFC, spatialRef = ssdo.spatialRefString) self.reducePoly, self.reduceArea = reduceInfo self.reducePath = PATH.Path(self.reducePoly) if self.reducePoly == None: ARCPY.AddIDMessage("ERROR", 1170) raise SystemExit() descRed = ARCPY.Describe(self.reducedFC) redExtent = descRed.extent self.redEnvelope = UTILS.Envelope(redExtent) self.redTolerance = self.redEnvelope.tolerance UTILS.passiveDelete(self.reducedFC) #### Create Study Area Envelope #### descSA = ARCPY.Describe(self.studyAreaFC) self.extentSA = descSA.extent self.envelopeSA = UTILS.Envelope(self.extentSA) envCoordsSA = self.envelopeSA.envelope self.minX, self.minY, self.maxX, self.maxY = envCoordsSA self.studyAreaPath = PATH.Path(self.studyAreaPoly)