def getLogRasterStatistic(self, Characteristic):
        '''
        This method returns a the natural log of values returned from Raster Statistic. This is only used for TWI at the moment.
        
        Original outline for this code was pulled from getPointFeatureDensity.
        '''
        ML = None
        result = {Characteristic.Name: None}
        try:
            self._sm("Computing " + Characteristic.Name)
            ML = MapLayer(MapLayerDef(Characteristic.MapLayers[0]))
            if not ML.Activated:
                raise Exception("Map Layer could not be activated.")

            rastStat = super(StreamStatsNationalOps,
                             self).getRasterStatistic(ML.Dataset, self.mask,
                                                      "MEAN")

            result[Characteristic.Name] = np.log(rastStat)

        except:
            tb = traceback.format_exc()
            self._sm(arcpy.GetMessages(), 'GP')
            self._sm("Anthops percentImpervious" + tb, "ERROR", 71)
            result[Characteristic.Name] = None

        finally:
            #Cleans up workspace
            ML = None

        return result
    def getPointFeatureDensity(self, Characteristic):
        '''
        Computes feature count per unit area.
        '''
        ML = None
        result = {Characteristic.Name: 0}
        try:
            self._sm("Computing " + Characteristic.Name)
            ML = MapLayer(MapLayerDef(Characteristic.MapLayers[0]))

            if not ML.Activated:
                raise Exception("Map Layer could not be activated.")

            totArea = self.getAreaSqMeter(
                self.mask) * Shared.CF_SQMETERS2SQKILOMETER
            count = super(StreamStatsNationalOps,
                          self).getFeatureCount(ML.Dataset, self.mask)

            result[Characteristic.Name] = count / totArea

        except:
            tb = traceback.format_exc()
            self._sm(arcpy.GetMessages(), 'GP')
            self._sm(
                "getPointFeatureDensity " + Characteristic.Name + " " + tb,
                "ERROR", 71)
            result[Characteristic.Name] = float('nan')

        finally:
            #Cleans up workspace
            ML = None

        return result
    def getRasterPercent(self, Characteristic):
        '''
        Computes the percent of a whole. Useful for calculating percent impervious from the NLCD data,
            percent irrigated agriculture using MIRAD data, and NWALT data.
        '''
        ML = None
        result = {Characteristic.Name: None}
        try:
            self._sm("Computing " + Characteristic.Name)
            ML = MapLayer(MapLayerDef(Characteristic.MapLayers[0]))
            if not ML.Activated:
                raise Exception("Map Layer could not be activated.")

            result[Characteristic.Name] = super(
                StreamStatsNationalOps, self).getRasterPercent(
                    ML.Dataset, self.mask, Characteristic.ClassCodes
                ) * Characteristic.MultiplicationFactor

        except:
            tb = traceback.format_exc()
            self._sm(arcpy.GetMessages(), 'GP')
            self._sm("Anthops percentImpervious" + tb, "ERROR", 71)
            result[Characteristic.Name] = None

        finally:
            #Cleans up workspace
            ML = None

        return result
    def getFeatureStatistic(self, Characteristic):
        '''
        Computes feature stat.
        '''
        ML = None
        result = {Characteristic.Name: 0}
        try:
            self._sm("Computing " + Characteristic.Name)
            ML = MapLayer(MapLayerDef(Characteristic.MapLayers[0]))

            if not ML.Activated:
                raise Exception("Map Layer could not be activated.")

            tot = super(StreamStatsNationalOps,
                        self).getFeatureStatistic(ML.Dataset, self.mask,
                                                  Characteristic.Method,
                                                  Characteristic.QueryField,
                                                  Characteristic.WhereClause)

            result[Characteristic.Name] = tot[Characteristic.QueryField][
                Characteristic.Method]

        except:
            tb = traceback.format_exc()
            self._sm(arcpy.GetMessages(), 'GP')
            self._sm(
                "getPointFeatureDensity " + Characteristic.Name + " " + tb,
                "ERROR", 71)
            result[Characteristic.Name] = float('nan')

        finally:
            #Cleans up workspace
            ML = None

        return result
    def getStoragePerUnitArea(self, Characteristic):
        '''
        Calculates the Storage per unit area. Is used for computing things
            such as computing the Reservoir storage from National Inventory of Dams (NID)
        '''
        ML = None
        result = {Characteristic.Name: 0}
        try:
            self._sm("Computing " + Characteristic.Name)
            ML = MapLayer(MapLayerDef(Characteristic.MapLayers[0]))
            ML_sr = arcpy.Describe(ML.Dataset).spatialReference

            arcpy.env.workspace = self._TempLocation
            if not ML.Activated:
                raise Exception("Map Layer could not be activated.")

            #This calculation should probably be changed depending on what is needed.
            #   I'm guessing this should be a function in Shared.py
            totArea = self.getAreaSqMeter(
                self.mask
            ) * Shared.CF_SQMETERS2SQKILOMETER  #Put ConversionFactor here?
            #spatial overlay
            #cursor and sum
            with arcpy.da.SearchCursor(self.spatialOverlay(
                    ML.Dataset, self.mask),
                                       Characteristic.QueryField,
                                       spatial_reference=ML_sr) as source_curs:
                for row in source_curs:
                    val = WIMLib.Shared.try_parse(row[0], None)
                    result[Characteristic.Name] += float(
                        val
                    ) * Shared.CF_ACR2SQKILOMETER / totArea  #Put ConversionFactor here?
                #next
            #end with
        except:
            tb = traceback.format_exc()
            self._sm(arcpy.GetMessages(), 'GP')
            self._sm("ReservoirStorage" + tb, "ERROR", 71)
            result[Characteristic.Name] = float('nan')

        finally:
            #Cleans up workspace
            ML = None

        return result
    def getPrismStatistic(self, Characteristic):

        #Computes statistic for prism data. Changed by JWX. Indent block did not work.

        result = {Characteristic.Name: None}
        try:
            self._sm("Computing " + Characteristic.Name)
            ML = MapLayer(MapLayerDef(Characteristic.MapLayers[0]))

            if not ML.Activated:
                raise Exception("Map Layer could not be activated.")

            timeRange = [
                dt.strptime(str(x), '%m-%d-%Y')
                for x in Characteristic.TimeRange.split(';')
            ]

            result[Characteristic.Name] = super(
                StreamStatsNationalOps,
                self).getPrismStatistic(ML.Dataset, self.mask,
                                        Characteristic.Method, timeRange,
                                        Characteristic.TimeMethod,
                                        Characteristic.Data)

        except:
            tb = traceback.format_exc()
            self._sm(arcpy.GetMessages(), 'GP')
            self._sm(
                "getPrismStatistic error" + tb + " " + Characteristic.Name,
                "ERROR", 71)
            result[Characteristic.Name] = None

        finally:
            #Cleans up workspace
            ML = None

        return result
    def getRasterStatistic(self, Characteristic):
        '''
        Calculates the raster statistics using various passed methods
            such as Mean, Median, Mode, Max, and Min.
        '''
        ML = None
        result = {Characteristic.Name: None}
        try:
            self._sm("Computing " + Characteristic.Name)
            #ML = MapLayer(MapLayerDef(Characteristic.MapLayers[0]))
            ML = MapLayer(MapLayerDef(Characteristic.MapLayers[0]), "",
                          self.mask)
            if not ML.Activated:
                raise Exception("Map Layer could not be activated.")

            result[Characteristic.Name] = super(
                StreamStatsNationalOps, self).getRasterStatistic(
                    ML.Dataset, self.mask, Characteristic.Method
                ) * Characteristic.MultiplicationFactor
            result[Characteristic.Name + 'up'] = super(
                StreamStatsNationalOps, self).getRasterStatistic(
                    ML.Dataset, self.mask3, Characteristic.Method
                ) * Characteristic.MultiplicationFactor
        except:
            tb = traceback.format_exc()
            self._sm(arcpy.GetMessages(), 'GP')
            self._sm(
                "getRasterStatistic error" + tb + " " + Characteristic.Name,
                "ERROR", 71)
            result[Characteristic.Name] = None

        finally:
            #Cleans up workspace
            ML = None

        return result
Ejemplo n.º 8
0
    def Delineate(self, PourPoint, inmask=None):
        #http://pro.arcgis.com/en/pro-app/tool-reference/spatial-analyst/watershed.htm
        fdr = None
        sr = None
        mask = None
        datasetPath = None
        featurePath = None
        outWatershedRaster = None
        upCatch = None
        dstemp = None
        downCatch = None
        try:
            catchments = Config()["catchment"]
            arcpy.env.workspace = self._TempLocation
            self._sm("Delineating catchment")
            fdr = MapLayer(MapLayerDef("fdr"), "", PourPoint)

            if not fdr.Activated:
                raise Exception("Flow direction could not be activated.")

            fac = MapLayer(MapLayerDef("fac"), fdr.TileID)

            if not fac.Activated:
                raise Exception("Flow accumulation could not be activated.")

            sr = fdr.spatialreference
            if inmask is not None:
                mask = self.ProjectFeature(inmask, sr)

            datasetPath = arcpy.CreateFileGDB_management(
                self._WorkspaceDirectory, self.WorkspaceID + '.gdb')[0]
            featurePath = arcpy.CreateFeatureDataset_management(
                datasetPath, 'Layers', sr)[0]

            self._sm("creating workspace environment. " + datasetPath)
            arcpy.CheckOutExtension("Spatial")
            self._sm("Starting Delineation")
            arcpy.env.extent = arcpy.Describe(mask).extent

            #Build snap pour point then use it for watershed.
            #   Pour point search distance of 60 m is equal to two cells.
            outSnapPour = SnapPourPoint(PourPoint, fac.Dataset, 60)
            outWatershedRaster = Watershed(fdr.Dataset, outSnapPour)

            upCatch = os.path.join(featurePath, catchments["upstream"])
            arcpy.RasterToPolygon_conversion(outWatershedRaster, upCatch,
                                             "NO_SIMPLIFY")
            #strip downstream catchment from mask
            dstemp = arcpy.Erase_analysis(mask, upCatch, "dstemp")
            downCatch = self.__removePolygonHoles(dstemp, featurePath,
                                                  catchments["downstream"])
            self._sm(arcpy.GetMessages(), 'AHMSG')
            self._sm("Finished")
        except:
            tb = traceback.format_exc()
            self._sm("Delineation Error " + tb, "ERROR")

        finally:
            arcpy.CheckInExtension("Spatial")
            #Local cleanup
            if fdr is not None: del fdr
            if sr is not None: del sr
            if mask is not None: arcpy.Delete_management(mask)
            if dstemp is not None:
                arcpy.Delete_management(dstemp)
                dstemp = None
            for raster in arcpy.ListRasters("*", "GRID"):
                arcpy.Delete_management(raster)
                del raster
                raster = None
            if datasetPath is not None: del datasetPath
            if featurePath is not None: del featurePath
            if upCatch is not None:
                del upCatch
                upCatch = None
            if downCatch is not None:
                del downCatch
                downCatch = None
            arcpy.env.extent = ""
    def getVectorDensity(self, Characteristic):
        '''
        Is a modification of getPointFeatureDensity. Initially created to calculate the percent of dams per stream.
        This method is a mash-up of prior work done within this method and the getFeatureStatistic Method found in SpatialOps.py.
        Mashed-up by JWX.
        '''

        map = []
        analysisFeatures = []
        ML = None
        result = {Characteristic.Name: 0}
        try:
            self._sm("Computing " + Characteristic.Name)

            ML = MapLayer(MapLayerDef(Characteristic.MapLayers[0]), "",
                          self.mask)

            if not ML.Activated:
                raise Exception("Map Layer could not be activated.")

            spOverlayWhole = self.spatialOverlay(
                ML.Dataset, self.mask,
                "INTERSECTS")  #Added back after sumMain was removed
            analysisFeatures.append(spOverlayWhole[0])

            #Create query
            queryField = "{}".format(
                Characteristic.Field
            )  #Generalized to pass whatever field needed
            operator = Characteristic.Operator  #Generalized to whatever operator e.g. =, LIKE, !=
            if operator == "LIKE":  #If operator = LIKE, flanking "%" are needed
                keyword = "'%{}%'".format(Characteristic.Keyword)
            else:
                keyword = Characteristic.Keyword
            query = "{} {} {}".format(queryField, operator,
                                      keyword)  #Build query

            #Create sub-set feature class using query
            arcpy.MakeFeatureLayer_management(
                spOverlayWhole, "Subsetlayer")  #Make feature layer
            arcpy.SelectLayerByAttribute_management(
                "Subsetlayer", "NEW_SELECTION", query)  #Carry out selection
            outName = os.path.join(
                self._TempLocation,
                "vdtmp.shp")  #SHP has to be included for proper function
            arcpy.CopyFeatures_management(
                "Subsetlayer",
                outName)  #Copy out features to avoid selection errors
            arcpy.SelectLayerByAttribute_management("Subsetlayer",
                                                    "CLEAR_SELECTION")
            if arcpy.GetCount_management(outName).getOutput(
                    0) == "0":  #Catch if the dataset is blank
                self._sm(
                    "Warning: Subset feature is blank. Zero will be substituded."
                )
                result[Characteristic.Name] = 0  #If blank, result is zero
            else:
                analysisFeatures.append(outName)

            #Get methods and field for analysis
            statisticRules = Characteristic.Method
            Fields = Characteristic.MethField  #Method operation field (newly added to config.json)
            #methods = [x.strip() for x in statisticRules.split(';')]                                #Could be used to scale the method section
            #Fields = [x.strip() for x in fieldStr.split(';')]                                       #Could be used to scale the fields section
            map.append([Fields, statisticRules])  #Build statistics statement
            resultCalculation = []  #AN ARRAY TO CAPTURE VALUES***

            for feaure in analysisFeatures:  #NEEDED CALCULATE EVERYTHING***
                tblevalue = arcpy.Statistics_analysis(
                    feaure, os.path.join(self._TempLocation, "aftmp"), map)
                mappedFeilds = [x[1] + "_" + x[0] for x in map]
                cursor = arcpy.da.SearchCursor(tblevalue, mappedFeilds)
                for row in cursor:
                    resultCalculation.append(row[0])

            #Generate values for results
            if len(analysisFeatures) == 1:  #Catch streams only instances
                result[Characteristic.Name] = 0
            else:
                if resultCalculation[0] == 0:  #Catch canal only instances
                    result[Characteristic.Name] = 100
                else:
                    result[Characteristic.Name] = (
                        resultCalculation[1] /
                        resultCalculation[0]) * 100  #Otherwise carry out math

        except:
            tb = traceback.format_exc()
            self._sm(arcpy.GetMessages(), 'GP')
            self._sm("getVectorDensity " + Characteristic.Name + " " + tb,
                     "ERROR", 71)
            result[Characteristic.Name] = float('nan')

        finally:
            #Cleans up workspace
            ML = None
            arcpy.SelectLayerByAttribute_management(
                "Subsetlayer", "CLEAR_SELECTION")  #This was added by JWX

        return result
    def getNIDDistrubanceIndex(self, Characteristic):
        #
        #DI_d,g = sum (Storage_d*DA_d/DA_t)/
        #                   (P*DA_t)
        #Where:  DI_d,g      - Dams Disturbance Index for gage
        #        Storage_d   - Storage at dam, in acre feet
        #        DA_d        - Drainage area at dam, in acres
        #        DA_t        - Total Drainage area at gage, in acres
        #        P           - Average Annual Precipitation, in feet
        #
        result = {Characteristic.Name: 0}
        try:
            self._sm("Computing " + Characteristic.Name)
            nidML = MapLayer(MapLayerDef(
                Characteristic.MapLayers[0]))  #USGS_NID_2018
            precipML = MapLayer(MapLayerDef(
                Characteristic.MapLayers[1]))  #Precip

            if not nidML.Activated or not precipML.Activated:
                raise Exception("Map Layer could not be activated.")
            P = super(StreamStatsNationalOps, self).getRasterStatistic(
                precipML.Dataset, self.mask2,
                None) * 0.003280841666667  #mm2foot
            DA_t = self.getAreaSqMeter(
                self.mask2) * 0.000247105  #Sqrmeter2Acre

            nidFeatures = arcpy.MakeFeatureLayer_management(
                self.spatialOverlay(nidML.Dataset, self.mask2), "nidfeatures")

            #join tables
            for jn in Characteristic.JoinTables[0]:
                jnfld = Characteristic.JoinField[:
                                                 10]  #trim 8 char to account for nidFeatures being a shp (fields are limited to 8 char length)
                arcpy.AddJoin_management(
                    nidFeatures, jnfld,
                    os.path.join(nidML.Path, nidML.DatasetName, jn['table']),
                    jn['key'], 'KEEP_COMMON')
            #next join
            fields = [
                fld['table'] + "." + fld['QueryField']
                for fld in Characteristic.JoinTables[0]
            ]

            sum = 0
            with arcpy.da.SearchCursor(nidFeatures, fields) as source_curs:
                for row in source_curs:
                    Storage_d = row[0]  #Acre_feet
                    DA_d = row[1]  #Acre
                    sum += Storage_d * (DA_d / DA_t)
                #next
            #end with

            result[Characteristic.Name] = sum / (P * DA_t)

        except:
            tb = traceback.format_exc()
            self._sm(arcpy.GetMessages(), 'GP')
            self._sm(
                "getPointFeatureDensity " + Characteristic.Name + " " + tb,
                "ERROR", 71)
            result[Characteristic.Name] = float('nan')

        finally:
            #Cleans up workspace
            ML = None

        return result