示例#1
0
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]
示例#3
0
    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)