Example #1
0
def topographic_radiation(raw_aspect, radiation_output):
    """
    Description: calculates 32-bit float topographic radiation
    Inputs: 'raw_aspect' -- an input raw aspect raster
            'radiation_output' -- an output topographic radiation raster
    Returned Value: Returns a raster dataset on disk
    Preconditions: requires an input raw aspect raster
    """

    # Import packages
    import arcpy
    from arcpy.sa import Con
    from arcpy.sa import Cos
    from arcpy.sa import Raster

    # Set overwrite option
    arcpy.env.overwriteOutput = True

    # Calculate topographic radiation aspect index
    print('\t\tCalculating topographic radiation aspect index...')
    numerator = 1 - Cos((3.142 / 180) * (Raster(raw_aspect) - 30))
    radiation_index = numerator / 2

    # Convert negative aspect values
    print('\t\tConverting negative aspect values...')
    out_raster = Con(Raster(raw_aspect) < 0, 0.5, radiation_index)
    out_raster.save(radiation_output)
Example #2
0
def combineProposedWithCurrentDebit(anthroPath, uniqueProposedSubtypes):
    for subtype in uniqueProposedSubtypes:
        # Merge proposed and current feature rasters
        currentAnthroFeature = Raster(os.path.join(anthroPath, subtype))
        proposedAnthroFeature = Raster("Proposed_" + subtype)
        postAnthroFeature = Con(IsNull(proposedAnthroFeature),
                                currentAnthroFeature, proposedAnthroFeature)
        postAnthroFeature.save(os.path.join("Post_" + subtype))
Example #3
0
def create_mask(path_to_temp):
    arcpy.CheckOutExtension('Spatial')
    inputrasters = arcpy.GetParameterAsText(1).split(";")
    rasterlist = []
    for elements in inputrasters:
        rasterobject = Raster(elements)
        rasterlist.append(rasterobject)
    rasterlistSum = sum(rasterlist)                     
    outcon = Con(IsNull(rasterlistSum) == 0,1)          # result raster has 1 when value meets value and NoData when value meets NoData
    outcon.save(join(path_to_temp,"mask"))              # filename is 'mask'
    #arcpy.CheckInExtension('Spatial')                  
    path_to_mask = join(path_to_temp,"mask")
    if arcpy.Exists(path_to_mask):
        arcpy.AddMessage("Creating mask.")
    return path_to_mask
Example #4
0
def calcConiferPost(coniferTreatmentArea, Conifer_Cover):
    arcpy.AddMessage("Calculating post-project conifer modifier")
    # Add field Conifer to use when converting to raster
    inTable = coniferTreatmentArea
    fieldName = "Conifer"
    fieldType = "SHORT"
    expression = 0
    arcpy.AddField_management(inTable, fieldName, fieldType)
    arcpy.CalculateField_management(inTable, fieldName, expression,
                                    "PYTHON_9.3", "")

    # Convert to raster
    in_features = coniferTreatmentArea
    value_field = "Conifer"
    out_rasterdataset = "Proposed_Conifer_Cover"
    cell_assignment = "MAXIMUM_AREA"
    priority_field = "Conifer"
    cellSize = 30

    coniferRaster = arcpy.PolygonToRaster_conversion(in_features,
                                                     value_field,
                                                     out_rasterdataset,
                                                     cell_assignment,
                                                     priority_field,
                                                     cellSize)

    # Mask existing conifer cover
    coniferPost = Con(IsNull(coniferRaster), Conifer_Cover, coniferRaster)
    coniferPost.save("Post_Conifer_Cover")

    # Calculate neighborhood statistics
    in_raster = coniferPost
    radius = 400
    neighborhood = NbrCircle(radius, "MAP")
    statistics_type = "MEAN"

    coniferCover400 = FocalStatistics(in_raster, neighborhood, statistics_type)

    # Reclassify to get Post_Conifer_Modifier
    in_raster = coniferCover400
    reclass_field = "VALUE"
    remapTable = [[0, 1, 100], [1, 2, 28], [2, 3, 14], [3, 4, 9], [4, 5, 6],
                  [5, 7, 3], [7, 8, 2], [8, 9, 1], [9, 100, 0]]
    coniferModifierPost100 = Reclassify(in_raster, reclass_field,
                                        RemapRange(remapTable))
    coniferModifierPost = Float(coniferModifierPost100) / 100

    return coniferModifierPost
def surface_relief(elevation_input, relief_output):
    """
    Description: calculates 32-bit float surface relief ratio
    Inputs: 'elevation_input' -- an input raster digital elevation model
            'relief_output' -- an output surface relief ratio raster
    Returned Value: Returns a raster dataset on disk
    Preconditions: requires an input elevation raster
    """

    # Import packages
    import arcpy
    from arcpy.sa import Con
    from arcpy.sa import Float
    from arcpy.sa import FocalStatistics
    from arcpy.sa import NbrRectangle

    # Set overwrite option
    arcpy.env.overwriteOutput = True

    # Define a neighborhood variable
    neighborhood = NbrRectangle(5, 5, "CELL")

    # Calculate local minimum
    print('\t\tCalculating local minimum...')
    local_minimum = FocalStatistics(elevation_input, neighborhood, 'MINIMUM',
                                    'DATA')

    # Calculate local maximum
    print('\t\tCalculating local maximum...')
    local_maximum = FocalStatistics(elevation_input, neighborhood, 'MAXIMUM',
                                    'DATA')

    # Calculate local mean
    print('\t\tCalculating local mean...')
    local_mean = FocalStatistics(elevation_input, neighborhood, 'MEAN', 'DATA')

    # Calculate maximum drop
    print('\t\tCalculating maximum drop...')
    maximum_drop = Float(local_maximum - local_minimum)

    # Calculate standardized drop
    print('\t\tCalculating standardized drop...')
    standardized_drop = Float(local_mean - local_minimum) / maximum_drop

    # Calculate surface relief ratio
    print('\t\tCalculating surface relief ratio...')
    out_raster = Con(maximum_drop == 0, 0, standardized_drop)
    out_raster.save(relief_output)
Example #6
0
def linear_aspect(raw_aspect, aspect_output):
    """
    Description: calculates 32-bit float linear aspect
    Inputs: 'raw_aspect' -- an input raw aspect raster
            'aspect_output' -- an output linear aspect raster
    Returned Value: Returns a raster dataset on disk
    Preconditions: requires an input DEM
    """

    # Import packages
    import arcpy
    from arcpy.sa import ATan2
    from arcpy.sa import Con
    from arcpy.sa import Cos
    from arcpy.sa import FocalStatistics
    from arcpy.sa import Mod
    from arcpy.sa import NbrRectangle
    from arcpy.sa import Raster
    from arcpy.sa import SetNull
    from arcpy.sa import Sin

    # Set overwrite option
    arcpy.env.overwriteOutput = True

    # Define a neighborhood variable
    neighborhood = NbrRectangle(3, 3, "CELL")

    # Calculate aspect transformations
    print('\t\tTransforming raw aspect to linear aspect...')
    setNull_aspect = SetNull(
        Raster(raw_aspect) < 0, (450.0 - Raster(raw_aspect)) / 57.296)
    sin_aspect = Sin(setNull_aspect)
    cos_aspect = Cos(setNull_aspect)
    sum_sin = FocalStatistics(sin_aspect, neighborhood, "SUM", "DATA")
    sum_cos = FocalStatistics(cos_aspect, neighborhood, "SUM", "DATA")
    mod_aspect = Mod(
        ((450 - (ATan2(sum_sin, sum_cos) * 57.296)) * 100), 36000
    ) / 100  # The *100 and 36000(360*100) / 100 allow for two decimal points since Fmod appears to be gone
    out_raster = Con((sum_sin == 0) & (sum_cos == 0), -1, mod_aspect)

    # Save output raster file
    out_raster.save(aspect_output)
def greennessMask(composite, ndi_thres, outpath, cutobject):
    '''
    composite: composite of RGB and TIR imagery produced during TIR 
               mosaicking and georeferencing
    ndi_thres: threshold for the greeness index. Pixels with values above will 
               be maintained
    outpath:   path to folder to save outputs
    cutobject: (optional) image which is clipped to the ndi threshold extent
    '''
                
    # Get raster bands from composite (RG values)
    red = Raster(composite + '\Band_1')
    green = Raster(composite + '\Band_2')
    # Get thermal and mask band
    mask = Raster(composite + '\Band_6')
                
    # Calculate greenness index NGRDI
    red = Float(red)
    green = Float(green)
    ndi = (green - red)/(green + red)
    
    del red
    del green
    
    ndi_clip = Con((mask == 65535), ndi, 0)
    del mask
    del ndi
    
    ndi_masked = Con(ndi_clip >= ndi_thres, ndi_clip, 0)
    del ndi_clip
                
    composite_name = os.path.split(composite)[1]
    ndi_file_masked = composite_name.replace('Composite', 'NDI')
    ndi_file_masked = ndi_file_masked.replace('_rect', '')
    # ndi_masked.save(os.path.join(outpath, ndi_file_masked))
            
    if cutobject:
        cutobj = Raster(cutobject)           
        masked_obj = Con(ndi_masked > ndi_thres, cutobj, -99)
        masked_obj_file = ndi_file_masked.replace('NDI', 'Obj')
        masked_obj.save(os.path.join(outpath, masked_obj_file))
Example #8
0
def function(outputFolder,
             preprocessFolder,
             lsOption,
             slopeAngle,
             soilOption,
             soilData,
             soilCode,
             lcOption,
             landCoverData,
             landCoverCode,
             rData,
             saveFactors,
             supportData,
             rerun=False):

    try:
        # Set temporary variables
        prefix = os.path.join(arcpy.env.scratchGDB, "rusle_")

        supportCopy = prefix + "supportCopy"
        soilResample = prefix + "soilResample"
        lcResample = prefix + "lcResample"
        rainResample = prefix + "rainResample"
        supportResample = prefix + "supportResample"
        soilClip = prefix + "soilClip"
        landCoverClip = prefix + "landCoverClip"
        rainClip = prefix + "rainClip"
        supportClip = prefix + "supportClip"
        DEMSlopeCut = prefix + "DEMSlopeCut"
        DEMSlopeRad = prefix + "DEMSlopeRad"
        upslopeArea = prefix + "upslopeArea"
        soilJoin = prefix + "soilJoin"
        lcJoin = prefix + "lcJoin"
        rFactor = prefix + "rFactor"
        lsFactor = prefix + "lsFactor"
        kFactor = prefix + "kFactor"
        cFactor = prefix + "cFactor"
        pFactor = prefix + "pFactor"
        soilLossInt = prefix + "soilLossInt"
        landCoverRas = prefix + "landCoverRas"
        soilRas = prefix + "soilRas"
        dataMask = prefix + "dataMask"

        # Get input study area mask
        files = common.getFilenames('preprocess', preprocessFolder)
        studyMask = files.studyareamask
        inputLC = files.lc_ras
        inputSoil = files.soil_ras
        DEMSlopePerc = files.slopeRawPer
        DEMSlope = files.slopeHydDeg
        hydFAC = files.hydFAC
        rawDEM = files.rawDEM
        streamInvRas = files.streamInvRas

        # Set output filenames
        files = common.getFilenames('rusle', outputFolder)
        soilLoss = files.soilloss

        if saveFactors:
            # if RUSLE factor layers are to be saved

            rFactor = files.rFactor
            lsFactor = files.lsFactor
            kFactor = files.kFactor
            cFactor = files.cFactor
            pFactor = files.pFactor

        reconOpt = common.getInputValue(preprocessFolder, 'Recondition_DEM')

        ####################
        ### Check inputs ###
        ####################

        codeBlock = 'Check if new inputs are in a projected coordinate systems'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            inputs = [rData]

            optInputs = [soilData, landCoverData, supportData]
            for data in optInputs:
                if data is not None:
                    inputs.append(data)

            for data in inputs:
                spatialRef = arcpy.Describe(data).spatialReference

                if spatialRef.Type == "Geographic":
                    # If any of the inputs are not in a projected coordinate system, the tool exits with a warning
                    log.error('Data: ' + str(data))
                    log.error(
                        'This data has a Geographic Coordinate System. It must have a Projected Coordinate System.'
                    )
                    sys.exit()

            log.info(
                'All new inputs are in a projected coordinate system, proceeding.'
            )

            progress.logProgress(codeBlock, outputFolder)

        try:

            # Set environment and extents to DEM
            RawDEM = Raster(rawDEM)

            arcpy.env.extent = RawDEM
            arcpy.env.mask = RawDEM
            arcpy.env.cellSize = RawDEM
            arcpy.env.compression = "None"

            cellsizedem = float(
                arcpy.GetRasterProperties_management(rawDEM,
                                                     "CELLSIZEX").getOutput(0))

            log.info("Calculation extent set to DEM data extent")

        except Exception:
            log.error("Environment and extent conditions not set correctly")
            raise

        codeBlock = 'Convert any vector inputs to raster'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            if landCoverData is not None:
                lcFormat = arcpy.Describe(landCoverData).dataType

                if lcFormat in ['ShapeFile', 'FeatureClass']:

                    arcpy.PolygonToRaster_conversion(landCoverData,
                                                     landCoverCode,
                                                     landCoverRas,
                                                     "CELL_CENTER", "",
                                                     cellsizedem)
                    log.info('Land cover raster produced')

                else:
                    arcpy.CopyRaster_management(landCoverData, landCoverRas)

            if soilData is not None:
                soilFormat = arcpy.Describe(soilData).dataType

                if soilFormat in ['ShapeFile', 'FeatureClass']:

                    arcpy.PolygonToRaster_conversion(soilData, soilCode,
                                                     soilRas, "CELL_CENTER",
                                                     "", cellsizedem)
                    log.info('Soil raster produced')

                else:
                    arcpy.CopyRaster_management(soilData, soilRas)

            progress.logProgress(codeBlock, outputFolder)

        codeBlock = 'Resample down to DEM cell size'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            # Resample down to DEM cell size
            log.info("Resampling inputs down to DEM cell size")

            resampledRainTemp = arcpy.sa.ApplyEnvironment(rData)
            resampledRainTemp.save(rainResample)
            del resampledRainTemp

            if soilData is not None:
                resampledSoilTemp = arcpy.sa.ApplyEnvironment(soilRas)
                resampledSoilTemp.save(soilResample)
                del resampledSoilTemp

                # Delete soil raster
                arcpy.Delete_management(soilRas)

            if landCoverData is not None:
                resampledLCTemp = arcpy.sa.ApplyEnvironment(landCoverRas)
                resampledLCTemp.save(lcResample)
                del resampledLCTemp

                # Delete land cover raster
                arcpy.Delete_management(landCoverRas)

            if supportData is not None:

                arcpy.CopyRaster_management(supportData, supportCopy)
                resampledPTemp = arcpy.sa.ApplyEnvironment(supportCopy)
                resampledPTemp.save(supportResample)
                del resampledPTemp

                # Delete support raster
                arcpy.Delete_management(supportCopy)

            log.info("Inputs resampled")

            progress.logProgress(codeBlock, outputFolder)

        codeBlock = 'Clip inputs'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            log.info("Clipping inputs")

            arcpy.Clip_management(rainResample,
                                  "#",
                                  rainClip,
                                  studyMask,
                                  clipping_geometry="ClippingGeometry")

            # Delete resampled R-factor
            arcpy.Delete_management(rainResample)

            if soilData is not None:
                arcpy.Clip_management(soilResample,
                                      "#",
                                      soilClip,
                                      studyMask,
                                      clipping_geometry="ClippingGeometry")

                # Delete resampled soil
                arcpy.Delete_management(soilResample)

            if landCoverData is not None:
                arcpy.Clip_management(lcResample,
                                      "#",
                                      landCoverClip,
                                      studyMask,
                                      clipping_geometry="ClippingGeometry")

                # Delete resampled land cover
                arcpy.Delete_management(lcResample)

            if supportData is not None:
                arcpy.Clip_management(supportResample,
                                      "#",
                                      supportClip,
                                      studyMask,
                                      clipping_geometry="ClippingGeometry")

                # Delete resampled support data
                arcpy.Delete_management(supportResample)

            log.info("Inputs clipped")

            progress.logProgress(codeBlock, outputFolder)

        codeBlock = 'Check against study area mask'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            inputs = [rainClip]

            optInputs = [soilClip, landCoverClip, supportClip]
            for data in optInputs:
                if arcpy.Exists(data):
                    inputs.append(data)

            for data in inputs:
                dataMask = common.extractRasterMask(data)
                common.checkCoverage(dataMask, studyMask, data)
                del dataMask

            progress.logProgress(codeBlock, outputFolder)

        ####################################
        ### Rainfall factor calculations ###
        ####################################

        codeBlock = 'Produce R-factor layer'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            # Copy resampled raster
            arcpy.CopyRaster_management(rainClip, rFactor)

            # Delete clipped R-factor
            arcpy.Delete_management(rainClip)

            log.info("R-factor layer produced")

            progress.logProgress(codeBlock, outputFolder)

        ######################################################
        ### Slope length and steepness factor calculations ###
        ######################################################

        codeBlock = 'Produce LS-factor layer'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            # Calculate the threshold slope angle in percent
            lsFactorRad = float(slopeAngle) * (math.pi / 180.0)
            riseRun = math.tan(lsFactorRad)
            cutoffPercent = riseRun * 100.0

            if lsOption == 'SlopeLength':

                log.info(
                    "Calculating LS-factor based on slope length and steepness only"
                )

                # Produce slope cutoff raster
                DEMSlopeCutTemp = Con(
                    Raster(DEMSlopePerc) > float(cutoffPercent),
                    float(cutoffPercent), Raster(DEMSlopePerc))
                DEMSlopeCutTemp.save(DEMSlopeCut)
                del DEMSlopeCutTemp

                # Calculate the parts of the LS-factor equation separately
                lsCalcA = (cellsizedem / 22.0)**0.5
                lsCalcB = 0.065 + (0.045 * Raster(DEMSlopeCut)) + (
                    0.0065 * Power(Raster(DEMSlopeCut), 2.0))

                # Calculate the LS-factor
                lsOrigTemp = lsCalcA * lsCalcB
                lsOrigTemp.save(lsFactor)

                # Delete temporary files
                del lsCalcB
                del lsOrigTemp
                arcpy.Delete_management(DEMSlopeCut)

                log.info("LS-factor layer produced")

            elif lsOption == 'UpslopeArea':

                if reconOpt == 'false':
                    log.error(
                        'Cannot calculate LS-factor including upslope contributing area on unreconditioned DEM'
                    )
                    log.error(
                        'Rerun the preprocessing tool to recondition the DEM')
                    sys.exit()

                log.info(
                    "Calculating LS-factor including upslope contributing area"
                )

                # Produce slope cutoff raster
                DEMSlopeCutTemp = Con(
                    Raster(DEMSlope) > float(slopeAngle), float(slopeAngle),
                    Raster(DEMSlope))
                DEMSlopeCutTemp.save(DEMSlopeCut)
                del DEMSlopeCutTemp

                # Convert from degrees to radian
                DEMSlopeRadTemp = Raster(DEMSlopeCut) * 0.01745
                DEMSlopeRadTemp.save(DEMSlopeRad)
                del DEMSlopeRadTemp

                # Currently hardcoded, but should have them as options in future
                m = 0.5
                n = 1.2

                upslopeAreaTemp = Raster(hydFAC) * float(cellsizedem)
                upslopeAreaTemp.save(upslopeArea)
                del upslopeAreaTemp

                lsFactorTemp = (m + 1) * Power(
                    Raster(upslopeArea) / 22.1, float(m)) * Power(
                        Sin(Raster(DEMSlopeRad)) / 0.09, float(n))
                lsFactorTemp.save(lsFactor)
                del lsFactorTemp

                # Delete temporary files
                arcpy.Delete_management(DEMSlopeCut)
                arcpy.Delete_management(DEMSlopeRad)
                arcpy.Delete_management(upslopeArea)

                log.info("LS-factor layer produced")

            progress.logProgress(codeBlock, outputFolder)

        ################################
        ### Soil factor calculations ###
        ################################

        codeBlock = 'Produce K-factor layer'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            if soilOption == 'PreprocessSoil':

                # Use the soil from the preprocessFolder
                arcpy.CopyRaster_management(inputSoil, soilClip)

                kTable = os.path.join(configuration.tablesPath,
                                      "rusle_hwsd.dbf")
                arcpy.JoinField_management(soilClip, "VALUE", kTable,
                                           "MU_GLOBAL")
                arcpy.CopyRaster_management(soilClip, soilJoin)

                # Delete temporary files
                arcpy.Delete_management(soilClip)

                kOrigTemp = Lookup(soilJoin, "K_Stewart")
                kOrigTemp.save(kFactor)

                # Delete temporary files
                del kOrigTemp
                arcpy.Delete_management(soilJoin)

            elif soilOption == 'LocalSoil':

                # User input is their own K-factor dataset
                kOrigTemp = Raster(soilClip)
                kOrigTemp.save(kFactor)

                # Delete temporary files
                del kOrigTemp
                arcpy.Delete_management(soilClip)

            else:
                log.error('Invalid soil erodibility option')
                sys.exit()

            log.info("K-factor layer produced")

            progress.logProgress(codeBlock, outputFolder)

        #################################
        ### Cover factor calculations ###
        #################################

        codeBlock = 'Produce C-factor layer'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            if lcOption == 'PrerocessLC':

                # Use LC from the preprocess folder

                arcpy.CopyRaster_management(inputLC, landCoverClip)

                cTable = os.path.join(configuration.tablesPath,
                                      "rusle_esacci.dbf")

                arcpy.JoinField_management(landCoverClip, "VALUE", cTable,
                                           "LC_CODE")
                arcpy.CopyRaster_management(landCoverClip, lcJoin)

                arcpy.Delete_management(landCoverClip)

                cOrigTemp = Lookup(lcJoin, "CFACTOR")
                cOrigTemp.save(cFactor)

                # Delete temporary files
                del cOrigTemp
                arcpy.Delete_management(lcJoin)

            elif lcOption == 'LocalCfactor':

                # User input is their own C-factor dataset

                cOrigTemp = Raster(landCoverClip)
                cOrigTemp.save(cFactor)

                # Delete temporary files
                del cOrigTemp
                arcpy.Delete_management(landCoverClip)

            else:
                log.error('Invalid C-factor option')
                sys.exit()

            log.info("C-factor layer produced")

            progress.logProgress(codeBlock, outputFolder)

        #####################################
        ### Support practice calculations ###
        #####################################

        codeBlock = 'Produce P-factor layer'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            if supportData is not None:
                arcpy.CopyRaster_management(supportClip, pFactor)
                log.info("P-factor layer produced")

                # Delete temporary files
                arcpy.Delete_management(supportClip)

            progress.logProgress(codeBlock, outputFolder)

        ##############################
        ### Soil loss calculations ###
        ##############################

        codeBlock = 'Produce soil loss layer'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            if supportData is not None:
                soilLossTemp = Raster(rFactor) * Raster(lsFactor) * Raster(
                    kFactor) * Raster(cFactor) * Raster(pFactor)

            else:
                soilLossTemp = Raster(rFactor) * Raster(lsFactor) * Raster(
                    kFactor) * Raster(cFactor)

            if lsOption == 'UpslopeArea':
                soilLossTemp = soilLossTemp * Raster(streamInvRas)
                soilLossTemp.save(soilLoss)

            else:
                soilLossTemp.save(soilLoss)

            log.info("RUSLE function completed successfully")

            progress.logProgress(codeBlock, outputFolder)

        return soilLoss

    except Exception:
        arcpy.AddError("RUSLE function failed")
        raise

    finally:
        # Remove feature layers from memory
        try:
            for lyr in common.listFeatureLayers(locals()):
                arcpy.Delete_management(locals()[lyr])
                exec(lyr + ' = None') in locals()
        except Exception:
            pass
Example #9
0
def main():
    # GET PARAMETER VALUES
    Map_Units_Provided = arcpy.GetParameterAsText(0)  # optional
    Proposed_Modified_Features_Provided = arcpy.GetParameterAsText(
        1)  # optional
    Project_Name = arcpy.GetParameterAsText(2)

    # DEFINE DIRECTORIES
    # Get the pathname to this script
    scriptPath = sys.path[0]
    arcpy.AddMessage("Script folder: " + scriptPath)
    arcpy.AddMessage("Python version: " + sys.version)
    # Construct pathname to workspace
    if Map_Units_Provided:
        projectGDB = arcpy.Describe(Map_Units_Provided).path
    elif Proposed_Modified_Features_Provided:
        projectGDB = arcpy.Describe(Proposed_Modified_Features_Provided).path
    else:
        arcpy.AddMessage("Please provide either a Map_Units or " +
                         "Proposed_Modified_Features layer.")
        sys.exit(0)
    arcpy.AddMessage("Project geodatabase: " + projectGDB)
    Project_Folder = arcpy.Describe(projectGDB).path
    arcpy.AddMessage("Project folder:" + Project_Folder)

    # Instantiate a cheStandard object
    cheStandard = cohqt.cheStandard(projectGDB, scriptPath)

    # ENVIRONMENT SETTINGS
    # Set workspaces
    arcpy.env.workspace = projectGDB
    scratch_folder = os.path.join(arcpy.Describe(projectGDB).path, 'scratch')
    if arcpy.Exists(scratch_folder):
        pass
    else:
        arcpy.CreateFolder_management(
            arcpy.Describe(projectGDB).path, 'scratch')
    arcpy.env.scratchWorkspace = scratch_folder
    # Overwrite outputs
    arcpy.env.overwriteOutput = True

    # DEFINE GLOBAL VARIABLES
    Parameter_Values = cheStandard.ParameterValues
    ConiferModifier = cheStandard.ConiferModifier
    GrSG_LDI = cheStandard.GrSG_LDI
    LekPresenceRaster = cheStandard.LekPresenceRaster
    Lek_Distance_Modifier = cheStandard.LekDistanceModifier
    SageModifier = cheStandard.SageModifier
    GrSG_Habitat = cheStandard.GrSGHabitatRaster
    MigrationModifier = cheStandard.MuleDeerMigrationMod
    WinterModifier = cheStandard.MuleDeerWinterMod
    SummerModifier = cheStandard.MuleDeerSummerMod
    MuleDeer_LDI = cheStandard.MuleDeerLDI
    emptyRaster = cheStandard.EmptyRaster
    BWMD_Open = cheStandard.BWMD_Open
    GrSG_Range = cheStandard.GrSGHabitat
    Mule_Range = cheStandard.MuleDeerHabitat
    cellSize = arcpy.GetRasterProperties_management(emptyRaster,
                                                    "CELLSIZEX").getOutput(0)

    # Filenames for feature classes or rasters used by this script
    MAP_UNITS = "Map_Units"
    PROPOSED_MODIFIED_FEATURES = "Proposed_Modified_Features"
    CREDIT_PROJECT_AREA = "Credit_Project_Area"
    CONIFER_TREATMENT_AREA = "Conifer_Treatment_Area"

    # Filenames for feature class and rasters created by this script
    INDIRECT_IMPACT_AREA = "Indirect_Impact_Area"
    ANALYSIS_AREA = "Analysis_Area"
    MAP_UNITS_DISSOLVE = "Map_Units_Dissolve"
    # GrSG Filenames
    CURRENT_ANTHRO_DISTURBANCE = "GRSG_Pre_Anthro_Disturbance"
    PROJECTED_ANTHRO_DISTURBANCE = "GRSG_Post_Anthro_Disturbance"
    GRSG_PRE_BREEDING = "GRSG_Pre_Breeding"
    GRSG_PRE_SUMMER = "GRSG_Pre_Summer"
    GRSG_PRE_WINTER = "GRSG_Pre_Winter"
    GRSG_POST_BREEDING = "GRSG_Post_Breeding"
    GRSG_POST_SUMMER = "GRSG_Post_Summer"
    GRSG_POST_WINTER = "GRSG_Post_Winter"
    POST_CONIFER_MODIFIER = "Post_Conifer_Modifier"
    # Mule Deer Filenames
    CURRENT_ANTHRO_DISTURBANCE_MD = "MuleDeer_Pre_Anthro_Disturbance"
    PROJECTED_ANTHRO_DISTURBANCE_MD = "MuleDeer_Post_Anthro_Disturbance"
    MULE_PRE_SUMMER = "MuleDeer_Pre_Summer"
    MULE_PRE_MIGRATION = "MuleDeer_Pre_Migration"
    MULE_PRE_WINTER = "MuleDeer_Pre_Winter"
    MULE_POST_SUMMER = "MuleDeer_Post_Summer"
    MULE_POST_MIGRATION = "MuleDeer_Post_Migration"
    MULE_POST_WINTER = "MuleDeer_Post_Winter"

    # ------------------------------------------------------------------------

    # FUNCTION CALLS
    # Check out Spatial Analyst extension
    hqtlib.CheckOutSpatialAnalyst()

    # Check provided layers
    if not Map_Units_Provided and not Proposed_Modified_Features_Provided:
        arcpy.AddError("ERROR:: Please provide a 'Map_Units' and/or "
                       "'Proposed_Modified_Features' feature.")
        sys.exit(0)

    if not Proposed_Modified_Features_Provided:
        # Ensure Proposed_Modified_Features does not exist
        if arcpy.Exists("Proposed_Modified_Features"):
            arcpy.AddError("ERROR:: A 'Proposed_Modified_Features' layer "
                           "was detected in the project's geodatabase. "
                           "Provide the 'Proposed_Modified_Features' layer "
                           "and re-run Credit Tool 2.")
            sys.exit(0)

    if Map_Units_Provided:
        # Clear selection, if present
        util.ClearSelectedFeatures(Map_Units_Provided)

        # Check provided layer
        feature = Map_Units_Provided
        required_fields = ["Map_Unit_ID", "Map_Unit_Name"]
        no_null_fields = ["Map_Unit_ID"]
        expected_fcs = [CREDIT_PROJECT_AREA]
        hqtlib.CheckPolygonInput(feature, required_fields, expected_fcs,
                                 no_null_fields)

        # Update Map Units layer with provided layer
        provided_input = Map_Units_Provided
        parameter_name = MAP_UNITS
        preserve_existing = False
        Map_Units = util.AdoptParameter(provided_input, parameter_name,
                                        preserve_existing)

        # Add Map Units layer to map
        layerFile = cheStandard.getLayerFile("MapUnits.lyr")
        util.AddToMap(Map_Units, layerFile)

        # Provide location of Credit Project Area
        Credit_Project_Area = CREDIT_PROJECT_AREA

    if Proposed_Modified_Features_Provided:
        # Clear selection, if present
        util.ClearSelectedFeatures(Proposed_Modified_Features_Provided)

        # Check provided layer
        required_fields = ["Type", "Subtype"]
        no_null_fields = required_fields
        expected_fcs = None
        hqtlib.CheckPolygonInput(Proposed_Modified_Features_Provided,
                                 required_fields, expected_fcs, no_null_fields)

        # Update Proposed_Modified_Features with provided layer
        provided_input = Proposed_Modified_Features_Provided
        parameterName = PROPOSED_MODIFIED_FEATURES
        preserve_existing = False
        Proposed_Modified_Features = util.AdoptParameter(
            provided_input, parameterName, preserve_existing)

        # Add Proposed Modified Features layer to map
        layerFile = cheStandard.getLayerFile("DebitProjectArea.lyr")
        util.AddToMap(Proposed_Modified_Features, layerFile)

        # Update message
        arcpy.AddMessage("Creating the area of indirect benefit")

        # Create Credit_Project_Area for projects that propose to modify
        # anthropogenic features
        # Create the Indirect_Impact_Area
        in_data = Proposed_Modified_Features
        out_name = INDIRECT_IMPACT_AREA
        Indirect_Impact_Area = hqtlib.CreateIndirectImpactArea(
            in_data, Parameter_Values, out_name)

        # Add field "Indirect"
        input_feature = Indirect_Impact_Area
        fieldsToAdd = ["Indirect"]
        fieldTypes = ["TEXT"]
        util.AddFields(input_feature, fieldsToAdd, fieldTypes)

        # Update field 'Indirect' to equal 'True'
        with arcpy.da.UpdateCursor(Indirect_Impact_Area,
                                   fieldsToAdd) as cursor:
            for row in cursor:
                row[0] = "True"
                cursor.updateRow(row)

        if Map_Units_Provided:
            # Merge with Credit_Project_Boundary
            fileList = [Map_Units_Provided, Indirect_Impact_Area]
            out_name = "in_memory/Credit_Project_Boundary"
            Project_Area = arcpy.Union_analysis(fileList, out_name)
        else:
            Project_Area = Indirect_Impact_Area

        # Eliminate areas of non-habitat to create Credit_Project_Area
        out_name = CREDIT_PROJECT_AREA
        habitat_bounds = cheStandard.HabitatMgmtArea
        Credit_Project_Area = hqtlib.EliminateNonHabitat(
            Project_Area, out_name, habitat_bounds)

    # Detect habitat types impacted directly or indirectly
    is_grsg = cohqt.DetectHabitat(Credit_Project_Area, GrSG_Range)
    is_mule = cohqt.DetectHabitat(Credit_Project_Area, Mule_Range)

    # Update message
    arcpy.AddMessage("Dissolving all multi-part map units to create "
                     "Map_Units_Dissolve")

    # Dissolve Map Units
    in_features = MAP_UNITS
    allowable_fields = ["Map_Unit_ID", "Map_Unit_Name", "Indirect"]
    out_name = MAP_UNITS_DISSOLVE
    anthro_features = None
    Map_Units_Dissolve = hqtlib.DissolveMapUnits(in_features, allowable_fields,
                                                 out_name, anthro_features)

    # Update message
    arcpy.AddMessage("Adding Map_Units_Dissolve to map")

    # Add layer to map document
    feature = Map_Units_Dissolve
    layerFile = cheStandard.getLayerFile("MapUnits.lyr")
    util.AddToMap(feature, layerFile, zoom_to=True)

    # Update message
    arcpy.AddMessage("Calculating area in acres for each map unit")

    # Calculate Area
    hqtlib.CalcAcres(Map_Units_Dissolve)

    # Update message
    arcpy.AddMessage("Adding transect field to Map Units Dissolve")

    # Add transects field to map units table
    fields = ["Transects"]
    fieldTypes = ["SHORT"]
    util.AddFields(Map_Units_Dissolve, fields, fieldTypes)

    # Update message
    arcpy.AddMessage("Creating Analysis Area")

    # Create Analysis Area
    out_name = ANALYSIS_AREA
    Analysis_Area = hqtlib.CreateAnalysisArea(Credit_Project_Area,
                                              Parameter_Values, out_name)

    # Add Analysis_Area to map
    layerFile = cheStandard.getLayerFile("AnalysisArea.lyr")
    util.AddToMap(Analysis_Area, layerFile, zoom_to=True)

    # Set processing extent to Analysis_Area
    arcpy.env.extent = ANALYSIS_AREA

    ### GREATER SAGE-GROUSE ANTHRO DIST & MODIFIERS ###
    if is_grsg:

        # Update message
        arcpy.AddMessage("Calculating proportion of each map unit within 1 km "
                         "of a lek")

        # Calculate proportion of map unit within 1 km of a lek
        inZoneData = Map_Units_Dissolve
        inValueRaster = cheStandard.LekPresenceRaster
        zoneField = "Map_Unit_ID"
        outTable = "Proportion_Lek"
        hqtlib.CalcZonalStats(inZoneData, zoneField, inValueRaster, outTable)

        # Join the zonal statistic to the Map Units Dissolve table
        field_name = "PropLek"
        hqtlib.JoinMeanToTable(inZoneData, outTable, zoneField, field_name)

        # Update message
        arcpy.AddMessage(
            "Calculating proportion of each map unit in the mesic "
            "precip zone")

        # Calculate Proportion of each map unit in the mesic precip zone
        inZoneData = Map_Units_Dissolve
        inValueRaster = cheStandard.Precip
        zoneField = "Map_Unit_ID"
        outTable = "Proportion_Mesic"
        hqtlib.CalcZonalStats(inZoneData, zoneField, inValueRaster, outTable)

        # Join the zonal statistic to the Map Units Dissolve table
        field_name = "PropMesic"
        hqtlib.JoinMeanToTable(inZoneData, outTable, zoneField, field_name)

        # Update message
        arcpy.AddMessage("Calculating pre-project anthropogenic "
                         "disturbance modifier for greater sage-grouse")

        # Calculate Current_Anthro_Disturbance
        dist_field = "GrSG_Dist"
        weight_field = "GrSG_Weight"
        term = cheStandard.CreditTerms[0]
        unique_proposed_subtypes = []
        anthro_disturbance_type = "Pre"

        Current_Anthro_Disturbance = cohqt.CalcAnthroDisturbance(
            Parameter_Values, term, unique_proposed_subtypes,
            anthro_disturbance_type, cheStandard, dist_field, weight_field,
            cellSize, emptyRaster)
        Current_Anthro_Disturbance.save(CURRENT_ANTHRO_DISTURBANCE)

        # Update message
        arcpy.AddMessage("Current_Anthro_Disturbance Calculated")
        arcpy.AddMessage("Calculating Pre-Project Habitat Modifiers for"
                         "Greater Sage-Grouse")

        # Calculate pre-project cumulative habitat modifiers
        winterHabitatPre = cohqt.calcWinterHabitatGRSG(
            Current_Anthro_Disturbance, ConiferModifier, GrSG_LDI,
            GrSG_Habitat)
        LSDMWinterPre = cohqt.applyLekUpliftModifierPre(
            winterHabitatPre, LekPresenceRaster)
        breedingHabitatPre = cohqt.calcBreedingHabitatGRSG(
            Current_Anthro_Disturbance, ConiferModifier, GrSG_LDI,
            Lek_Distance_Modifier, GrSG_Habitat)
        LSDMBreedingPre = cohqt.applyLekUpliftModifierPre(
            breedingHabitatPre, LekPresenceRaster)
        summerHabitatPre = cohqt.calcSummerHabitatGRSG(
            Current_Anthro_Disturbance, ConiferModifier, GrSG_LDI,
            SageModifier, GrSG_Habitat)
        LSDMSummerPre = cohqt.applyLekUpliftModifierPre(
            summerHabitatPre, LekPresenceRaster)
        seasonalHabitatRasters = [
            LSDMWinterPre, LSDMBreedingPre, LSDMSummerPre
        ]

        # Save outputs
        # winterHabitatPre.save(GRSG_PRE_WINTER)
        LSDMWinterPre.save(GRSG_PRE_WINTER)
        # breedingHabitatPre.save(GRSG_PRE_BREEDING)
        LSDMBreedingPre.save(GRSG_PRE_BREEDING)
        # summerHabitatPre.save(GRSG_PRE_SUMMER)
        LSDMSummerPre.save(GRSG_PRE_SUMMER)

        # Initialize list of uplift rasters to combine for LekUpliftModifier
        upliftRasters = []
        if arcpy.Exists(CONIFER_TREATMENT_AREA):
            # Calculate post-project conifer modifier
            Conifer_Cover = cheStandard.ConiferCover
            coniferModifierPost = cohqt.calcConiferPost(
                CONIFER_TREATMENT_AREA, Conifer_Cover)
            coniferModifierPost.save(POST_CONIFER_MODIFIER)

            # Calculate uplift from conifer removal
            coniferUplift = cohqt.calcUplift(ConiferModifier,
                                             coniferModifierPost)
            upliftRasters.append(coniferUplift)

        else:
            coniferModifierPost = ConiferModifier

        if arcpy.Exists(PROPOSED_MODIFIED_FEATURES):
            # Prepare proposed anthropogenic features
            unique_proposed_subtypes = cohqt.convertProposedToRasterCredit(
                PROPOSED_MODIFIED_FEATURES, cellSize)

            anthroPath = cheStandard.AnthroFeaturePath
            cohqt.combineProposedWithCurrentCredit(anthroPath,
                                                   unique_proposed_subtypes)

            # Update message
            arcpy.AddMessage("Calculating post-project anthropogenic "
                             "disturbance modifier for greater sage-grouse")

            # Calculate post-project anthropogenic disturbance
            term = cheStandard.CreditTerms[1]
            anthro_disturbance_type = "Post"

            Projected_Anthro_Disturbance = cohqt.CalcAnthroDisturbance(
                Parameter_Values, term, unique_proposed_subtypes,
                anthro_disturbance_type, cheStandard, dist_field, weight_field,
                cellSize, emptyRaster)

            Projected_Anthro_Disturbance.save(PROJECTED_ANTHRO_DISTURBANCE)

            # Update message
            arcpy.AddMessage("Projected_Anthro_Disturbance Calculated")

            # Calculate uplift from anthro feature removal
            anthroUplift = cohqt.calcUplift(Current_Anthro_Disturbance,
                                            Projected_Anthro_Disturbance)
            upliftRasters.append(anthroUplift)

            # Update message
            arcpy.AddMessage(
                "Merging indirect benefits area and map units layer")

            # Combine the Map Units layer and Indirect Impact Layer
            indirect_benefit_area = CREDIT_PROJECT_AREA
            mgmt_map_units = Map_Units_Dissolve
            Map_Units_Dissolve = hqtlib.AddIndirectBenefitArea(
                indirect_benefit_area, mgmt_map_units)

        else:
            Projected_Anthro_Disturbance = Current_Anthro_Disturbance

            # Add Indirect field to Map Units layer and populate with False
            # Add field "Indirect"
            feature = Map_Units_Dissolve
            fieldsToAdd = ["Indirect"]
            fieldTypes = ["TEXT"]
            util.AddFields(feature, fieldsToAdd, fieldTypes)

            # Update field to equal "False"
            with arcpy.da.UpdateCursor(feature, fieldsToAdd) as cursor:
                for row in cursor:
                    row[0] = "False"
                    cursor.updateRow(row)

        # Calc zonal stats for pre-project modifiers (three seasons)
        term = cheStandard.CreditTerms[0]
        for season, raster in zip(cheStandard.GrSGSeasons,
                                  seasonalHabitatRasters):
            # Update message
            arcpy.AddMessage("Summarizing GrSG " + term + " " + season)

            # Calculate zonal statistics for each map unit
            inZoneData = Map_Units_Dissolve
            inValueRaster = raster
            zoneField = "Map_Unit_ID"
            outTable = "GrSG_Stats_" + term + "_" + season
            hqtlib.CalcZonalStats(inZoneData, zoneField, inValueRaster,
                                  outTable)

            # Join the zonal statistic to the Map Units Dissolve table
            field_name = "GrSG_" + term + "_" + season
            hqtlib.JoinMeanToTable(inZoneData, outTable, zoneField, field_name)

        if arcpy.Exists("Conifer_Treatment_Area") or \
                arcpy.Exists("Anthro_Features_Removed"):

            # Update message
            arcpy.AddMessage("Calculating Lek Uplift Modifier")

            # Calculate Lek Uplift Modifier
            lekUpliftModifier = cohqt.calcLekUpliftModifier(
                LekPresenceRaster, upliftRasters)
            lekUpliftModifier.save("Lek_Uplift_Modifier")

            # Update message
            arcpy.AddMessage("Calculating Post-Project Habitat Modifiers")

            # Calculate post-project cumulative habtiat modifiers
            winterHabitatPost = cohqt.calcWinterHabitatGRSG(
                Projected_Anthro_Disturbance, ConiferModifier, GrSG_LDI,
                GrSG_Habitat)
            LSDMWinterPost = cohqt.applyLekUpliftModifierPost(
                winterHabitatPost, LekPresenceRaster, lekUpliftModifier)
            breedingHabitatPost = cohqt.calcBreedingHabitatGRSG(
                Projected_Anthro_Disturbance, ConiferModifier, GrSG_LDI,
                Lek_Distance_Modifier, GrSG_Habitat)
            LSDMBreedingPost = cohqt.applyLekUpliftModifierPost(
                breedingHabitatPost, LekPresenceRaster, lekUpliftModifier)
            summerHabitatPost = cohqt.calcSummerHabitatGRSG(
                Projected_Anthro_Disturbance, ConiferModifier, GrSG_LDI,
                SageModifier, GrSG_Habitat)
            LSDMSummerPost = cohqt.applyLekUpliftModifierPost(
                summerHabitatPost, LekPresenceRaster, lekUpliftModifier)

            seasonalHabitatRasters = [
                LSDMWinterPost, LSDMBreedingPost, LSDMSummerPost
            ]

            # Save outputs
            # winterHabitatPost.save("Post_Seasonal_Winter")
            LSDMWinterPost.save(GRSG_POST_WINTER)
            # breedingHabitatPost.save("Post_Seasonal_Breeding")
            LSDMBreedingPost.save(GRSG_POST_BREEDING)
            # summerHabitatPost.save("Post_Seasonal_Summer")
            LSDMSummerPost.save(GRSG_POST_SUMMER)

            # Calc zonal stats for post-project modifiers
            term = cheStandard.CreditTerms[1]
            for season, raster in zip(cheStandard.GrSGSeasons,
                                      seasonalHabitatRasters):
                # Update message
                arcpy.AddMessage("Summarizing GrSG " + term + " " + season)

                # Calculate zonal statistics for each map unit
                inZoneData = Map_Units_Dissolve
                inValueRaster = raster
                zoneField = "Map_Unit_ID"
                outTable = "GrSG_Stats_" + term + "_" + season
                hqtlib.CalcZonalStats(inZoneData, zoneField, inValueRaster,
                                      outTable)

                # Join the zonal statistic to the Map Units Dissolve table
                field_name = "GrSG_" + term + "_" + season
                hqtlib.JoinMeanToTable(inZoneData, outTable, zoneField,
                                       field_name)

        # Calculate Credit Intensity

    ### END GREATER SAGE-GROUSE ###

    ### MULE DEER ANTHRO DIST & MODIFIERS ###
    if is_mule:
        # Update message
        arcpy.AddMessage("Calculating pre-project anthropogenic disturbance "
                         "modifier for mule deer - process may repeat for "
                         "habitats in mixed PJ and open habitat")

        # # Calculat pre-project anthropogenic disturbance
        # dist_field = "MDO_Dist"
        # weight_field = "MDO_Weight"
        # term = cheStandard.CreditTerms[0]
        # unique_proposed_subtypes = []
        # anthro_disturbance_type = "Pre"
        #
        # Current_Anthro_Disturbance = hqtlib.cheCalcAnthroDisturbance(
        #     Parameter_Values, term, unique_proposed_subtypes,
        #     anthro_disturbance_type, cheStandard, dist_field, weight_field,
        #     cellSize, emptyRaster
        # )
        # Current_Anthro_Disturbance.save(CURRENT_ANTHRO_DISTURBANCE_MD)

        # Calculate pre-project anthropogenic disturbance
        # Calculate pre-project in PJ
        dist_field = "MDP_Dist"
        weight_field = "MDP_Weight"
        term = cheStandard.CreditTerms[0]
        unique_proposed_subtypes = []
        anthro_disturbance_type = "Pre"

        anthro_pj = cohqt.CalcAnthroDisturbance(Parameter_Values, term,
                                                unique_proposed_subtypes,
                                                anthro_disturbance_type,
                                                cheStandard, dist_field,
                                                weight_field, cellSize,
                                                emptyRaster)
        anthro_pj.save(CURRENT_ANTHRO_DISTURBANCE_MD + "_P")

        # Calculate pre-project in Open
        dist_field = "MDO_Dist"
        weight_field = "MDO_Weight"
        term = cheStandard.CreditTerms[0]
        unique_proposed_subtypes = []
        anthro_disturbance_type = "Pre"

        anthro_open = cohqt.CalcAnthroDisturbance(Parameter_Values,
                                                  term,
                                                  unique_proposed_subtypes,
                                                  anthro_disturbance_type,
                                                  cheStandard,
                                                  dist_field,
                                                  weight_field,
                                                  cellSize,
                                                  emptyRaster,
                                                  mask=BWMD_Open)
        anthro_open.save(CURRENT_ANTHRO_DISTURBANCE_MD + "_O")

        # Combine PJ and Open
        # If outside open, make 1
        anthro_open_only = Con(BWMD_Open == 1, anthro_open, 1)
        anthro_open_only.save(CURRENT_ANTHRO_DISTURBANCE_MD + "_OO")

        # Select minimum of pj and open rasters
        Current_Anthro_Disturbance = Con(anthro_open_only < anthro_pj,
                                         anthro_open_only, anthro_pj)
        Current_Anthro_Disturbance.save(CURRENT_ANTHRO_DISTURBANCE_MD)

        # Clean up
        arcpy.Delete_management("temp_masked_raster")
        # arcpy.Delete_management(CURRENT_ANTHRO_DISTURBANCE_MD + "_P")
        # arcpy.Delete_management(CURRENT_ANTHRO_DISTURBANCE_MD + "_O")
        # arcpy.Delete_management(CURRENT_ANTHRO_DISTURBANCE_MD + "_OO")

        # Update message
        arcpy.AddMessage("Calculating Pre-Project Habitat Modifiers")

        # Calculate pre-project cumulative habitat modifiers
        summerHabitatPre = cohqt.calcSummerHabitatMD(
            Current_Anthro_Disturbance,
            MuleDeer_LDI,
            SummerModifier,
            SuitableHabitat=None)
        # LSDMWinterPre = cohqt.applyLekUpliftModifierPre(summerHabitatPre,
        #                                                  LekPresenceRaster)
        migratoryHabitatPre = cohqt.calcMigratoryHabitatMD(
            Current_Anthro_Disturbance,
            MuleDeer_LDI,
            MigrationModifier,
            SuitableHabitat=None)
        # LSDMBreedingPre = cohqt.applyLekUpliftModifierPre(migratoryHabitatPre,
        #                                                    LekPresenceRaster)
        winterHabitatPre = cohqt.calcWinterHabitatMD(
            Current_Anthro_Disturbance,
            MuleDeer_LDI,
            WinterModifier,
            SuitableHabitat=None)
        # LSDMSummerPre = cohqt.applyLekUpliftModifierPre(winterHabitatPre,
        #                                                  LekPresenceRaster)
        seasonalHabitatRasters = [
            summerHabitatPre, migratoryHabitatPre, winterHabitatPre
        ]

        # Save outputs
        summerHabitatPre.save(MULE_PRE_SUMMER)
        # LSDMWinterPre.save("Pre_LSDM_Winter")
        migratoryHabitatPre.save(MULE_PRE_MIGRATION)
        # LSDMBreedingPre.save("Pre_LSDM_Breeding")
        winterHabitatPre.save(MULE_PRE_WINTER)
        # LSDMSummerPre.save("Pre_LSDM_Summer")

        # Update message
        arcpy.AddMessage("Current_Anthro_Disturbance Calculated")

        # Calc zonal stats for pre-project modifiers (three seasons)
        term = cheStandard.DebitTerms[0]
        for season, raster in zip(cheStandard.MuleDeerSeasons,
                                  seasonalHabitatRasters):
            # Update message
            arcpy.AddMessage("Summarizing Mule Deer " + term + " " + season)

            # Calculate zonal statistics for each map unit
            inZoneData = Map_Units_Dissolve
            inValueRaster = raster
            zoneField = "Map_Unit_ID"
            outTable = "Mule_Stats_" + term + "_" + season
            hqtlib.CalcZonalStats(inZoneData, zoneField, inValueRaster,
                                  outTable)

            # Join the zonal statistic to the Map Units Dissolve table
            field_name = "Mule_" + term + "_" + season
            hqtlib.JoinMeanToTable(inZoneData, outTable, zoneField, field_name)

        # # Calculate average of three seasonal habitat rasters pre-project
        # finalPreCumulative = hqtlib.calcAverageHabitatQuality(
        #     seasonalHabitatRasters
        # )
        # finalPreCumulative.save(CUMULATIVE_MODIFIER_PRE)

        if arcpy.Exists(PROPOSED_MODIFIED_FEATURES):
            # Update message
            arcpy.AddMessage("Calculating post-project anthropogenic "
                             "disturbance modifier")

            # Calculate post-project anthropogenic disturbance
            term = cheStandard.CreditTerms[1]
            anthro_disturbance_type = "Post"

            Projected_Anthro_Disturbance = cohqt.CalcAnthroDisturbance(
                Parameter_Values, term, unique_proposed_subtypes,
                anthro_disturbance_type, cheStandard, dist_field, weight_field,
                cellSize, emptyRaster)

            Projected_Anthro_Disturbance.save(PROJECTED_ANTHRO_DISTURBANCE_MD)

            # Update message
            arcpy.AddMessage("Projected_Anthro_Disturbance Calculated")

            # Calculate post-project cumulative habitat modifiers
            summerHabitatPost = cohqt.calcSummerHabitatMD(
                Projected_Anthro_Disturbance,
                MuleDeer_LDI,
                SummerModifier,
                SuitableHabitat=None)
            # LSDMWinterPost = cohqt.applyLekUpliftModifierPost(summerHabitatPost,
            #                                                  LekPresenceRaster)
            migratoryHabitatPost = cohqt.calcMigratoryHabitatMD(
                Projected_Anthro_Disturbance,
                MuleDeer_LDI,
                MigrationModifier,
                SuitableHabitat=None)
            # LSDMBreedingPost = cohqt.applyLekUpliftModifierPost(migratoryHabitatPost,
            #                                                    LekPresenceRaster)
            winterHabitatPost = cohqt.calcWinterHabitatMD(
                Projected_Anthro_Disturbance,
                MuleDeer_LDI,
                WinterModifier,
                SuitableHabitat=None)
            # LSDMSummerPost = cohqt.applyLekUpliftModifierPost(winterHabitatPost,
            #                                                  LekPresenceRaster)
            seasonalHabitatRasters = [
                summerHabitatPost, migratoryHabitatPost, winterHabitatPost
            ]

            # Save outputs
            summerHabitatPost.save(MULE_POST_SUMMER)
            # LSDMWinterPre.save("Pre_LSDM_Winter")
            migratoryHabitatPost.save(MULE_POST_MIGRATION)
            # LSDMBreedingPre.save("Pre_LSDM_Breeding")
            winterHabitatPost.save(MULE_POST_WINTER)
            # LSDMSummerPre.save("Pre_LSDM_Summer")

            # Calc zonal stats for pre-project modifiers (three seasons)
            term = cheStandard.DebitTerms[1]
            for season, raster in zip(cheStandard.MuleDeerSeasons,
                                      seasonalHabitatRasters):
                # Update message
                arcpy.AddMessage("Summarizing Mule Deer " + term + season)

                # Calculate zonal statistics for each map unit
                inZoneData = Map_Units_Dissolve
                inValueRaster = raster
                zoneField = "Map_Unit_ID"
                outTable = "Mule_Stats_" + term + season
                hqtlib.CalcZonalStats(inZoneData, zoneField, inValueRaster,
                                      outTable)

                # Join the zonal statistic to the Map Units Dissolve table
                field_name = "Mule_" + term + "_" + season
                hqtlib.JoinMeanToTable(inZoneData, outTable, zoneField,
                                       field_name)

            # # Calculate average of three seasonal habitat rasters post-project
            # finalPostCumulative = hqtlib.calcAverageHabitatQuality(
            #     seasonalHabitatRasters
            # )
            # finalPostCumulative.save(CUMULATIVE_MODIFIER_POST)

            # Calculate permanent cumulative habtiat modifiers

            # Update message
            arcpy.AddMessage("Calculating Mule Deer Benefit")

            # Calculate impact
            pre_fields = [
                "Mule_Pre_Summer", "Mule_Pre_Migration", "Mule_Pre_Winter"
            ]
            post_fields = [
                "Mule_Post_Summer", "Mule_Post_Migration", "Mule_Post_Winter"
            ]
            out_fields = [
                "Mule_Summer_Benefit", "Mule_Migration_Benefit",
                "Mule_Winter_Benefit"
            ]
            for i in range(len(pre_fields)):
                pre_field = pre_fields[i]
                post_field = post_fields[i]
                out_field = out_fields[i]
                cohqt.calcDebits(Map_Units_Dissolve, pre_field, post_field,
                                 out_field)

        # # Export data to Excel
        input_Tables = [MAP_UNITS_DISSOLVE]
        for table in input_Tables:
            hqtlib.ExportToExcel(table, Project_Folder, Project_Name)

    ### END MULE DEER ###
    if not is_grsg and not is_mule:
        arcpy.AddMessage("Impacts were not detected in any habitat type. "
                         "Please check credit project boundary and try "
                         "again")
    # Clean up
    for raster in arcpy.ListRasters("*_Subtype_Disturbance"):
        arcpy.Delete_management(raster)

    for raster in arcpy.ListRasters("*_Type_Disturbance"):
        arcpy.Delete_management(raster)

    arcpy.Delete_management("in_memory")

    # Save map document
    if arcpy.ListInstallations()[0] == 'arcgispro':
        p = arcpy.mp.ArcGISProject("CURRENT")
        p.save()
    else:
        mxd = arcpy.mapping.MapDocument("CURRENT")
        mxd.save()
Example #10
0
elif class_type == 'binary':
    other_val = 0
    tree_val = 1
    classified = Con(dsm_sl,
                     where_clause="Value<=19.241",
                     in_true_raster_or_constant=other_val,
                     in_false_raster_or_constant=Con(
                         dhm,
                         where_clause="Value<=0",
                         in_true_raster_or_constant=other_val,
                         in_false_raster_or_constant=tree_val))

arcpy.AddMessage("Cleaning classifications")

classified_path_raw = os.path.join(support_folder, 'classified_raw.tif')
classified.save(classified_path_raw)

classified_path_maj = os.path.join(support_folder, 'classified_maj.tif')
maj = arcpy.sa.MajorityFilter(classified_path_raw, "EIGHT", "HALF")
maj.save(classified_path_maj)

classified_path_clean = os.path.join(support_folder, 'classified_clean.tif')
cle = arcpy.sa.BoundaryClean(classified_path_maj, "DESCEND", "TWO_WAY")
cle.save(classified_path_clean)

arcpy.AddMessage("Converting to polygons")

classified_path_poly = os.path.join(out_folder, 'classified_poly.shp')
arcpy.RasterToPolygon_conversion(classified_path_clean, classified_path_poly,
                                 "SIMPLIFY")
Example #11
0
def main(classification_file, bpi_broad_std, bpi_fine_std,
         slope, bathy, out_raster=None):
    """
    Perform raster classification, based on classification mappings
    and provided raster derivatives (fine- and broad- scale BPI,
    slope, and the original raster). Outputs a classified raster.
    """
    try:
        # set up scratch workspace
        # FIXME: see issue #18
        # CON is very very picky. it generates GRID outputs by default, and the
        # resulting names must not exist. for now, push our temp results
        # to the output folder.
        out_workspace = os.path.dirname(out_raster)
        # make sure workspace exists
        utils.workspace_exists(out_workspace)
        arcpy.env.scratchWorkspace = out_workspace
        arcpy.env.workspace = out_workspace

        arcpy.env.overwriteOutput = True
        # Create the broad-scale Bathymetric Position Index (BPI) raster
        msg_text = ("Generating the classified grid, based on the provided"
                    " classes in '{}'.".format(classification_file))
        utils.msg(msg_text)

        # Read in the BTM Document; the class handles parsing a variety of inputs.
        btm_doc = utils.BtmDocument(classification_file)
        classes = btm_doc.classification()
        utils.msg("Parsing {} document... found {} classes.".format(
            btm_doc.doctype, len(classes)))

        grids = []
        key = {'0': 'None'}
        for item in classes:
            cur_class = str(item["Class"])
            cur_name = str(item["Zone"])
            utils.msg("Calculating grid for {}...".format(cur_name))
            key[cur_class] = cur_name
            out_con = None
            # here come the CONs:
            out_con = run_con(item["Depth_LowerBounds"],
                              item["Depth_UpperBounds"],
                              bathy, cur_class)
            out_con2 = run_con(item["Slope_LowerBounds"],
                               item["Slope_UpperBounds"],
                               slope, out_con, cur_class)
            out_con3 = run_con(item["LSB_LowerBounds"],
                               item["LSB_UpperBounds"],
                               bpi_fine_std, out_con2, cur_class)
            out_con4 = run_con(item["SSB_LowerBounds"],
                               item["SSB_UpperBounds"],
                               bpi_broad_std, out_con3, cur_class)

            if type(out_con4) == arcpy.sa.Raster:
                rast = utils.save_raster(out_con4, "con_{}.tif".format(cur_name))
                grids.append(rast)
            else:
                # fall-through: no valid values detected for this class.
                warn_msg = ("WARNING, no valid locations found for class"
                            " {}:\n".format(cur_name))
                classifications = {
                    'depth': (item["Depth_LowerBounds"], item["Depth_UpperBounds"]),
                    'slope': (item["Slope_LowerBounds"], item["Slope_UpperBounds"]),
                    'broad': (item["SSB_LowerBounds"], item["SSB_UpperBounds"]),
                    'fine': (item["LSB_LowerBounds"], item["LSB_UpperBounds"])
                }
                for (name, vrange) in classifications.items():
                    (vmin, vmax) = vrange
                    if vmin or vmax is not None:
                        if vmin is None:
                            vmin = ""
                        if vmax is None:
                            vmax = ""
                        warn_msg += "  {}: {{{}:{}}}\n".format(name, vmin, vmax)

                utils.msg(textwrap.dedent(warn_msg))

        if len(grids) == 0:
            raise NoValidClasses

        utils.msg("Creating Benthic Terrain Classification Dataset...")
        merge_grid = grids[0]
        for i in range(1, len(grids)):
            utils.msg("{} of {}".format(i, len(grids)-1))
            merge_grid = Con(merge_grid, grids[i], merge_grid, "VALUE = 0")
        arcpy.AddField_management(merge_grid, 'Zone', 'TEXT')
        rows = arcpy.UpdateCursor(merge_grid)
        for row in rows:
            val = str(row.getValue('VALUE'))
            if val in key:
                row.setValue('Zone', key[val])
                rows.updateRow(row)
            else:
                row.setValue('Zone', 'No Matching Zone')
                rows.updateRow(row)
        # writing Python like it's C
        del(rows)
        del(row)

        arcpy.env.rasterStatistics = "STATISTICS"
        # validate the output raster path
        out_raster = utils.validate_path(out_raster)
        utils.msg("Saving Output to {}".format(out_raster))
        merge_grid.save(out_raster)

        utils.msg("Complete.")

    except NoValidClasses as e:
        utils.msg(e, mtype='error')
    except Exception as e:
        if type(e) is ValueError:
            raise e
        utils.msg(e, mtype='error')

    try:
        utils.msg("Deleting intermediate data...")
        # Delete all intermediate raster data sets
        for grid in grids:
            arcpy.Delete_management(grid.catalogPath)
    except Exception as e:
        # hack -- swallowing this exception, because sometimes
        # refs are left around for these files.
        utils.msg("Failed to delete all intermediate data.", mtype='warning')
Example #12
0
def getLargePatchViewGrid(classValuesList, excludedValuesList, inLandCoverGrid,
                          landCoverValues, viewRadius, conValues,
                          minimumPatchSize, timer, saveIntermediates,
                          metricConst):
    # create class (value = 1) / other (value = 0) / excluded grid (value = 0) raster
    # define the reclass values
    classValue = 1
    excludedValue = 0
    otherValue = 0
    newValuesList = [classValue, excludedValue, otherValue]

    # generate a reclass list where each item in the list is a two item list: the original grid value, and the reclass value
    reclassPairs = getInOutOtherReclassPairs(landCoverValues, classValuesList,
                                             excludedValuesList, newValuesList)

    AddMsg((
        "{0} Reclassifying selected land cover class to 1. All other values = 0..."
    ).format(timer.split()))
    reclassGrid = Reclassify(inLandCoverGrid, "VALUE",
                             RemapValue(reclassPairs))

    ##calculate the big patches for LandCover

    AddMsg(("{0} Calculating size of excluded area patches...").format(
        timer.split()))
    regionGrid = RegionGroup(reclassGrid, "EIGHT", "WITHIN", "ADD_LINK")

    AddMsg(
        ("{0} Assigning {1} to patches >= minimum size threshold...").format(
            timer.split(), "1"))
    delimitedCOUNT = arcpy.AddFieldDelimiters(regionGrid, "COUNT")
    whereClause = delimitedCOUNT + " >= " + minimumPatchSize + " AND LINK = 1"
    burnInGrid = Con(regionGrid, classValue, 0, whereClause)

    # save the intermediate raster if save intermediates option has been chosen
    if saveIntermediates:
        namePrefix = metricConst.burnInGridName
        scratchName = arcpy.CreateScratchName(namePrefix, "", "RasterDataset")
        burnInGrid.save(scratchName)
        AddMsg(timer.split() + " Save intermediate grid complete: " +
               os.path.basename(scratchName))

    ##end of calculating the big patches for LandCover

    AddMsg((
        "{0} Performing focal SUM on reclassified raster with big patches using {1} cell radius neighborhood..."
    ).format(timer.split(), viewRadius))
    neighborhood = arcpy.sa.NbrCircle(int(viewRadius), "CELL")
    #focalGrid = arcpy.sa.FocalStatistics(reclassGrid == classValue, neighborhood, "SUM")
    focalGrid = arcpy.sa.FocalStatistics(burnInGrid == classValue,
                                         neighborhood, "SUM")

    AddMsg((
        "{0} Reclassifying focal SUM results into view = 1 and no-view = 0 binary raster..."
    ).format(timer.split()))
    #    delimitedVALUE = arcpy.AddFieldDelimiters(focalGrid,"VALUE")
    #    whereClause = delimitedVALUE+" = 0"
    #    viewGrid = Con(focalGrid, 1, 0, whereClause)
    whereValue = conValues[0]
    trueValue = conValues[1]
    viewGrid = Con(Raster(focalGrid) > whereValue, trueValue)
    return viewGrid
Example #13
0
def arc_catch_del(WD, boundary_shp, sites_shp, site_num_col='site', point_dis=1000, stream_depth=10, grid_size=8, pour_dis=20, streams='S:/Surface Water/shared\\GIS_base\\vector\\MFE_REC_rivers_no_1st.shp', dem='S:/Surface Water/shared\\GIS_base\\raster\\DEM_8m_2012\\linz_8m_dem', export_dir='results', overwrite_rasters=False):
    """
    Arcpy function to delineate catchments based on specific points, a polygon, and the REC rivers layer.
    Arcpy must be installed.
    Be careful that the folder path isn't too long!!! Do not have spaces in the path name!!! Arc sucks!!!

    Parameters:
    WD: str
        Working directory.
    boundary_shp: str
        The path to the shapefile polygon boundary extent.
    sites_shp: str
        The path to the sites shapefile.
    site_num_col: str
        The column in the sites_shp that contains the site IDs.
    point_dis: int
        The max distance to snap the sites to the nearest stream line.
    stream_depth: int
        The depth that the streams shapefile should be burned into the dem.
    grid_size: int
        The resolution of the dem.
    streams: str
        The path to the streams shapefile.
    dem: str
        The path to the dem.
    export_dir: str
        The subfolder where the results should be saved.
    overwrite_rasters: bool
        Should the flow direction and flow accumulation rasters be overwritten?

    Returns
    -------
    None
    """
    # load in the necessary arcpy libraries to import arcpy
    sys.path.append('C:\\Python27\\ArcGIS10.4\\Lib\\site-packages')
    sys.path.append(r'C:\Program Files (x86)\ArcGIS\Desktop10.4\arcpy')
    sys.path.append(r'C:\Program Files (x86)\ArcGIS\Desktop10.4\ArcToolbox\Scripts')
    sys.path.append(r'C:\Program Files (x86)\ArcGIS\Desktop10.4\bin')
    sys.path.append('C:\\Python27\\ArcGIS10.4\\lib')

    # Import packages
    import arcpy
    from arcpy import env
    from arcpy.sa import Raster, Con, IsNull, FlowDirection, FlowAccumulation, Fill, SnapPourPoint, Watershed
    #import ArcHydroTools as ah

    # Check out spatial analyst license
    arcpy.CheckOutExtension('Spatial')
    # Define functions

#    def snap_points(points, lines, distance):
#
#        import arcgisscripting, sys
#
#        gp = arcgisscripting.create()
#
#        # Load the Analysis toolbox so that the Near tool is available
#        gp.toolbox = "analysis"
#
#        # Perform the Near operation looking for the nearest line
#        # (from the lines Feature Class) to each point (from the
#        # points Feature Class). The third argument is the search
#        # radius - blank means to search as far as is needed. The
#        # fourth argument instructs the command to output the
#        # X and Y co-ordinates of the nearest point found to the
#        # NEAR_X and NEAR_Y fields of the points Feature Class
#        gp.near(points, lines, str(distance), "LOCATION")
#
#        # Create an update cursor for the points Feature Class
#        # making sure that the NEAR_X and NEAR_Y fields are included
#        # in the return data
#        rows = gp.UpdateCursor(points, "", "", "NEAR_X, NEAR_Y")
#
#        row = rows.Next()
#
#        # For each row
#        while row:
#            # Get the location of the nearest point on one of the lines
#            # (added to the file as fields by the Near operation above
#            new_x = row.GetValue("NEAR_X")
#            new_y = row.GetValue("NEAR_Y")
#
#            # Create a new point object with the new x and y values
#            point = gp.CreateObject("Point")
#            point.x = new_x
#            point.y = new_y
#
#            # Assign it to the shape field
#            row.shape = point
#
#            # Update the row data and move to the next row
#            rows.UpdateRow(row)
#            row = rows.Next()

    def snap_points(points, lines, distance):
        """
        Ogi's updated snap_points function.
        """

        points = arcpy.Near_analysis(points, lines, str(distance), "LOCATION")

        # Create an update cursor for the points Feature Class
        # making sure that the NEAR_X and NEAR_Y fields are included
        # in the return data
        with arcpy.da.UpdateCursor(points, ["NEAR_X", "NEAR_Y", "SHAPE@XY"]) as cursor:
            for row in cursor:
                x, y, shape_xy = row
                shape_xy = (x, y)
                cursor.updateRow([x, y, shape_xy])
        return(points)

    ### Parameters:
    ## input

    # Necessary to change
    env.workspace = WD
    boundary = boundary_shp
    sites_in = sites_shp

#    site_num_col = 'site'

    # May not be necessary to change
    final_export_dir = export_dir
#    streams = 'S:/Surface Water/shared\\GIS_base\\vector\\MFE_REC_rivers_no_1st.shp'
#    dem = 'S:/Surface Water/shared\\GIS_base\\raster\\DEM_8m_2012\\linz_8m_dem'

    env.extent = boundary
    arcpy.env.overwriteOutput = True

    ## output
    bound = 'bound_diss.shp'
    sites = 'sites_bound.shp'
    streams_loc = 'MFE_streams_loc.shp'
    dem_loc = 'dem_loc.tif'
    stream_diss = 'MFE_rivers_diss.shp'
    stream_rast = 'stream_rast.tif'
    dem_diff_tif = 'dem_diff.tif'
    dem_fill_tif = 'dem_fill.tif'
    fd_tif = 'fd1.tif'
    accu_tif = 'accu1.tif'
    catch_poly = 'catch_del.shp'

    if not os.path.exists(os.path.join(env.workspace, final_export_dir)):
        os.makedirs(os.path.join(env.workspace, final_export_dir))

    ##########################
    #### Processing

    ### Process sites and streams vectors

    # Dissolve boundary for faster processing
    arcpy.Dissolve_management(boundary, bound)

    # Clip sites and streams to boundary
    arcpy.Clip_analysis(streams, bound, streams_loc)
    arcpy.Clip_analysis(sites_in, bound, sites)

    # Snap sites to streams layer
    snap_points(sites, streams_loc, point_dis)

    # Dissolve stream network
    arcpy.Dissolve_management(streams_loc, stream_diss, "", "", "MULTI_PART", "DISSOLVE_LINES")

    # Add raster parameters to streams layer
    arcpy.AddField_management(stream_diss, "rast", "SHORT")
    arcpy.CalculateField_management(stream_diss, "rast", stream_depth, "PYTHON_9.3")

    ############################################
    ### Delineate catchments

    # Convert stream vector to raster
    arcpy.FeatureToRaster_conversion(stream_diss, 'rast', stream_rast, grid_size)

    ## Create the necessary flow direction and accumulation rasters if they do not already exist
    if os.path.exists(os.path.join(env.workspace, accu_tif)) & (not overwrite_rasters):
        accu1 = Raster(accu_tif)
        fd1 = Raster(fd_tif)
    else:
        # Clip the DEM to the study area
        print('clipping DEM to catchment area...')
        arcpy.Clip_management(dem, "1323813.1799 5004764.9257 1688157.0305 5360238.95", dem_loc, bound, "", "ClippingGeometry", "NO_MAINTAIN_EXTENT")

        # Fill holes in DEM
        print('Filling DEM...')
#        dem_fill = Fill(dem_loc)

        # Subtract stream raster from
        s_rast = Raster(stream_rast)
        dem_diff = Con(IsNull(s_rast), dem_loc, dem_loc - s_rast)
        dem_diff.save(dem_diff_tif)

        # Fill holes in DEM
        dem2 = Fill(dem_diff_tif)
        dem2.save(dem_fill_tif)

        # flow direction
        print('Flow direction...')
        fd1 = FlowDirection(dem2)
        fd1.save(fd_tif)

        # flow accu
        print('Flow accumulation...')
        accu1 = FlowAccumulation(fd1)
        accu1.save(accu_tif)

    # create pour points
    pp1 = SnapPourPoint(sites, accu1, pour_dis, site_num_col)

    # Determine the catchments for all points
    catch1 = Watershed(fd1, pp1)

    # Convert raster to polygon
    arcpy.RasterToPolygon_conversion(catch1, catch_poly, 'SIMPLIFY', 'Value')

    # Add in a field for the area of each catchment
    arcpy.AddField_management(catch_poly, "area_m2", "LONG")
    arcpy.CalculateField_management(catch_poly, "area_m2", 'round(!shape.area!)', "PYTHON_9.3")

    #### Check back in the spatial analyst license once done
    arcpy.CheckInExtension('Spatial')
Example #14
0
def getEdgeCoreGrid(m, lccObj, lccClassesDict, inLandCoverGrid,
                    PatchEdgeWidth_str, processingCellSize_str, timer,
                    shortName, scratchNameReference):
    # Get the lccObj values dictionary to determine if a grid code is to be included in the effective reporting unit area calculation
    lccValuesDict = lccObj.values
    #landCoverValues = raster.getRasterValues(inLandCoverGrid)
    landCoverValues = getRasterValues(inLandCoverGrid)

    # get the grid codes for this specified metric
    ClassValuesList = lccClassesDict[m].uniqueValueIds.intersection(
        landCoverValues)

    # get the frozenset of excluded values (i.e., values not to use when calculating the reporting unit effective area)
    ExcludedValueList = lccValuesDict.getExcludedValueIds().intersection(
        landCoverValues)

    # create grid where cover type of interest (e.g., forest) is coded 3, excluded values are coded 1, everything else is coded 2
    reclassPairs = []
    for val in landCoverValues:
        oldValNewVal = []
        oldValNewVal.append(val)
        if val in ClassValuesList:
            oldValNewVal.append(3)
            reclassPairs.append(oldValNewVal)
        elif val in ExcludedValueList:
            oldValNewVal.append(1)
            reclassPairs.append(oldValNewVal)
        else:
            oldValNewVal.append(2)
            reclassPairs.append(oldValNewVal)

    AddMsg(
        timer.split() +
        " Step 1 of 4: Reclassing land cover grid to Class = 3, Other = 2, and Excluded = 1..."
    )
    reclassGrid = Reclassify(inLandCoverGrid, "VALUE",
                             RemapValue(reclassPairs))

    AddMsg(timer.split() + " Step 2 of 4: Setting Class areas to Null...")
    delimitedVALUE = arcpy.AddFieldDelimiters(reclassGrid, "VALUE")
    otherGrid = SetNull(reclassGrid, 1, delimitedVALUE + " = 3")

    AddMsg(timer.split() + " Step 3 of 4: Finding distance from Other...")
    distGrid = EucDistance(otherGrid)

    AddMsg(timer.split() +
           " Step 4 of 4: Delimiting Class areas to Edge = 3 and Core = 4...")
    edgeDist = round(float(PatchEdgeWidth_str) * float(processingCellSize_str))

    zonesGrid = Con((distGrid >= edgeDist) & reclassGrid, 4, reclassGrid)

    # it appears that ArcGIS cannot process the BuildRasterAttributeTable request without first saving the raster.
    # This step wasn't the case earlier. Either ESRI changed things, or I altered something in ATtILA that unwittingly caused this. -DE
    namePrefix = shortName + "_" + "Raster" + m + PatchEdgeWidth_str
    scratchName = arcpy.CreateScratchName(namePrefix, "", "RasterDataset")
    scratchNameReference[0] = scratchName
    zonesGrid.save(scratchName)

    arcpy.BuildRasterAttributeTable_management(zonesGrid, "Overwrite")

    arcpy.AddField_management(zonesGrid, "CATEGORY", "TEXT", "#", "#", "10")
    updateCoreEdgeCategoryLabels(zonesGrid)

    return zonesGrid
Example #15
0
def createPatchRaster(m, lccObj, lccClassesDict, inLandCoverGrid, metricConst,
                      maxSeparation, minPatchSize, processingCellSize_str,
                      timer, scratchNameReference):
    # create a list of all the grid values in the selected landcover grid
    #landCoverValues = raster.getRasterValues(inLandCoverGrid)
    landCoverValues = getRasterValues(inLandCoverGrid)

    # for the selected land cover class, get the class codes found in the input landcover grid
    lccValuesDict = lccObj.values
    classValuesList = lccClassesDict[m].uniqueValueIds.intersection(
        landCoverValues)

    # get the frozenset of excluded values (i.e., values not to use when calculating the reporting unit effective area)
    excludedValuesList = lccValuesDict.getExcludedValueIds().intersection(
        landCoverValues)

    # create class (value = 3) / other (value = 0) / excluded grid (value = -9999) raster
    # define the reclass values
    classValue = metricConst.classValue
    excludedValue = metricConst.excludedValue
    otherValue = metricConst.otherValue
    newValuesList = [classValue, excludedValue, otherValue]

    # generate a reclass list where each item in the list is a two item list: the original grid value, and the reclass value
    reclassPairs = getInOutOtherReclassPairs(landCoverValues, classValuesList,
                                             excludedValuesList, newValuesList)

    AddMsg(timer.split() + " Reclassing land cover to Class:" + m + " = " +
           str(classValue) + ", Other = " + str(otherValue) +
           ", and Excluded = " + str(excludedValue) + "...")
    reclassGrid = Reclassify(inLandCoverGrid, "VALUE",
                             RemapValue(reclassPairs))

    # create patch raster where:
    #    clusters of cells within the input threshold distance are considered a single patch
    #    and patches below the input minimum size have been discarded

    # Ensure all parameter inputs are the appropriate number type
    intMaxSeparation = int(maxSeparation)
    intMinPatchSize = int(minPatchSize)

    # Check if Maximum Separation > 0 if it is then skip to regions group analysis otherwise run Euclidean distance
    if intMaxSeparation == 0:
        AddMsg(
            timer.split() +
            " Assigning unique numbers to each unconnected cluster of Class:" +
            m + "...")
        regionOther = RegionGroup(reclassGrid == classValue, "EIGHT", "CROSS",
                                  "ADD_LINK", "0")
    else:
        AddMsg(timer.split() + " Connecting clusters of Class:" + m +
               " within maximum separation distance...")
        fltProcessingCellSize = float(processingCellSize_str)
        maxSep = intMaxSeparation * float(processingCellSize_str)
        delimitedVALUE = arcpy.AddFieldDelimiters(reclassGrid, "VALUE")
        whereClause = delimitedVALUE + " < " + str(classValue)
        classRaster = SetNull(reclassGrid, 1, whereClause)
        eucDistanceRaster = EucDistance(classRaster, maxSep,
                                        fltProcessingCellSize)

        # Run Region Group analysis on UserEuclidPlus, ignores 0/NoData values
        AddMsg(
            timer.split() +
            " Assigning unique numbers to each unconnected cluster of Class:" +
            m + "...")
        UserEuclidRegionGroup = RegionGroup(eucDistanceRaster >= 0, "EIGHT",
                                            "CROSS", "ADD_LINK", "0")

        # Maintain the original boundaries of each patch
        regionOther = Con(reclassGrid == classValue, UserEuclidRegionGroup,
                          reclassGrid)

    if intMinPatchSize > 1:
        AddMsg(timer.split() +
               " Eliminating clusters below minimum patch size...")
        delimitedCOUNT = arcpy.AddFieldDelimiters(regionOther, "COUNT")
        whereClause = delimitedCOUNT + " < " + str(intMinPatchSize)
        regionOtherFinal = Con(regionOther, otherValue, regionOther,
                               whereClause)
    else:
        regionOtherFinal = regionOther

    # add the excluded class areas back to the raster if present
    if excludedValuesList:
        regionOtherExcluded = Con(reclassGrid == excludedValue, reclassGrid,
                                  regionOtherFinal)
    else:
        regionOtherExcluded = regionOtherFinal

    # The Patch Metrics tool appears to have trouble calculating its metrics when the raster area is large and the
    # regionOtherExcluded grid is treated as a raster object in memory and not saved as a raster on disk
    namePrefix = metricConst.shortName + "_" + m + "_PatchRast"
    scratchName = arcpy.CreateScratchName(namePrefix, "", "RasterDataset")
    regionOtherExcluded.save(scratchName)
    desc = arcpy.Describe(regionOtherExcluded)
    scratchNameReference[0] = desc.catalogPath

    return regionOtherExcluded
Example #16
0
def main(classification_file,
         bpi_broad_std,
         bpi_fine_std,
         slope,
         bathy,
         out_raster=None):
    """
    Perform raster classification, based on classification mappings
    and provided raster derivatives (fine- and broad- scale BPI,
    slope, and the original raster). Outputs a classified raster.
    """
    try:
        # set up scratch workspace
        # FIXME: see issue #18
        # CON is very very picky. it generates GRID outputs by default, and the
        # resulting names must not exist. for now, push our temp results
        # to the output folder.
        out_workspace = os.path.dirname(out_raster)
        # make sure workspace exists
        utils.workspace_exists(out_workspace)
        arcpy.env.scratchWorkspace = out_workspace
        arcpy.env.workspace = out_workspace

        arcpy.env.overwriteOutput = True
        # Create the broad-scale Bathymetric Position Index (BPI) raster
        msg_text = ("Generating the classified grid, based on the provided"
                    " classes in '{}'.".format(classification_file))
        utils.msg(msg_text)

        # Read in the BTM Document; the class handles parsing a variety of inputs.
        btm_doc = utils.BtmDocument(classification_file)
        classes = btm_doc.classification()
        utils.msg("Parsing {} document... found {} classes.".format(
            btm_doc.doctype, len(classes)))

        grids = []
        for item in classes:
            cur_class = str(item["Class"])
            cur_name = str(item["Zone"])
            utils.msg("Calculating grid for {}...".format(cur_name))
            out_con = None
            # here come the CONs:
            out_con = run_con(item["Depth_LowerBounds"],
                              item["Depth_UpperBounds"], bathy, cur_class)
            out_con2 = run_con(item["Slope_LowerBounds"],
                               item["Slope_UpperBounds"], slope, out_con,
                               cur_class)
            out_con3 = run_con(item["LSB_LowerBounds"],
                               item["LSB_UpperBounds"], bpi_fine_std, out_con2,
                               cur_class)
            out_con4 = run_con(item["SSB_LowerBounds"],
                               item["SSB_UpperBounds"], bpi_broad_std,
                               out_con3, cur_class)

            if type(out_con4) == arcpy.sa.Raster:
                rast = utils.save_raster(out_con4,
                                         "con_{}.tif".format(cur_name))
                grids.append(rast)
            else:
                # fall-through: no valid values detected for this class.
                warn_msg = ("WARNING, no valid locations found for class"
                            " {}:\n".format(cur_name))
                classifications = {
                    'depth':
                    (item["Depth_LowerBounds"], item["Depth_UpperBounds"]),
                    'slope':
                    (item["Slope_LowerBounds"], item["Slope_UpperBounds"]),
                    'broad':
                    (item["SSB_LowerBounds"], item["SSB_UpperBounds"]),
                    'fine': (item["LSB_LowerBounds"], item["LSB_UpperBounds"])
                }
                for (name, vrange) in classifications.items():
                    (vmin, vmax) = vrange
                    if vmin or vmax is not None:
                        if vmin is None:
                            vmin = ""
                        if vmax is None:
                            vmax = ""
                        warn_msg += "  {}: {{{}:{}}}\n".format(
                            name, vmin, vmax)

                utils.msg(textwrap.dedent(warn_msg))

        if len(grids) == 0:
            raise NoValidClasses

        utils.msg("Creating Benthic Terrain Classification Dataset...")
        merge_grid = grids[0]
        for i in range(1, len(grids)):
            utils.msg("{} of {}".format(i, len(grids) - 1))
            merge_grid = Con(merge_grid, grids[i], merge_grid, "VALUE = 0")

        arcpy.env.rasterStatistics = "STATISTICS"
        # validate the output raster path
        out_raster = utils.validate_path(out_raster)
        utils.msg("Saving Output to {}".format(out_raster))
        merge_grid.save(out_raster)
        utils.msg("Complete.")

    except NoValidClasses as e:
        utils.msg(e, mtype='error')
    except Exception as e:
        if type(e) is ValueError:
            raise e
        utils.msg(e, mtype='error')

    try:
        utils.msg("Deleting intermediate data...")
        # Delete all intermediate raster data sets
        for grid in grids:
            arcpy.Delete_management(grid.catalogPath)
    except Exception as e:
        # hack -- swallowing this exception, because sometimes
        # refs are left around for these files.
        utils.msg("Failed to delete all intermediate data.", mtype='warning')
Example #17
0
def main():
    # GET PARAMETER VALUES
    Proposed_Surface_Disturbance_Provided = arcpy.GetParameterAsText(0)
    Proposed_Modified_Features_Provided = arcpy.GetParameterAsText(
        1)  # optional

    # DEFINE DIRECTORIES
    # Get the pathname to this script
    scriptPath = sys.path[0]
    arcpy.AddMessage("Script folder: " + scriptPath)
    arcpy.AddMessage("Python version: " + sys.version)
    # Construct pathname to workspace
    projectGDB = arcpy.Describe(Proposed_Surface_Disturbance_Provided).path
    arcpy.AddMessage("Project geodatabase: " + projectGDB)

    # Instantiate a cheStandard object
    cheStandard = cohqt.cheStandard(projectGDB, scriptPath)

    # ENVIRONMENT SETTINGS
    # Set workspaces
    arcpy.env.workspace = projectGDB
    scratch_folder = os.path.join(arcpy.Describe(projectGDB).path, 'scratch')
    if arcpy.Exists(scratch_folder):
        pass
    else:
        arcpy.CreateFolder_management(
            arcpy.Describe(projectGDB).path, 'scratch')
    arcpy.env.scratchWorkspace = scratch_folder
    # Overwrite outputs
    arcpy.env.overwriteOutput = True

    # DEFINE GLOBAL VARIABLES
    Parameter_Values = cheStandard.ParameterValues
    habitat_bounds = cheStandard.HabitatMgmtArea
    ConiferModifier = cheStandard.ConiferModifier
    GrSG_LDI = cheStandard.GrSG_LDI
    LekPresenceRaster = cheStandard.LekPresenceRaster
    Lek_Distance_Modifier = cheStandard.LekDistanceModifier
    SageModifier = cheStandard.SageModifier
    GrSGHabitat = cheStandard.BWSGHab
    MuleDeerHabitat = cheStandard.BWMDHab
    emptyRaster = cheStandard.EmptyRaster
    MigrationModifier = cheStandard.MuleDeerMigrationMod
    WinterModifier = cheStandard.MuleDeerWinterMod
    SummerModifier = cheStandard.MuleDeerSummerMod
    MuleDeer_LDI = cheStandard.MuleDeerLDI
    BWMD_Open = cheStandard.BWMD_Open
    GrSG_Range = cheStandard.GrSGHabitat
    Mule_Range = cheStandard.MuleDeerHabitat
    cellSize = arcpy.GetRasterProperties_management(emptyRaster,
                                                    "CELLSIZEX").getOutput(0)

    # Filenames for feature classes or rasters used by this script
    PROPOSED_SURFACE_DISTURBANCE_DEBITS = "Proposed_Surface_Disturbance_Debits"

    # Filenames for feature classes or rasters created by this script
    ANALYSIS_AREA = "Analysis_Area"
    DEBIT_PROJECT_AREA = "Debit_Project_Area"
    INDIRECT_IMPACT_AREA = "Indirect_Impact_Area"
    INDIRECT_BENEFIT_AREA = "Indirect_Benefit_Area"
    PROPOSED_MODIFIED_FEATURES = "Proposed_Modified_Features"
    DEBIT_PROJECT_IMPACT = "GrSG_Impact"
    MAP_UNITS = "Map_Units"
    # GrSG Filenames
    LEK_DISTURBANCE_MODIFIER = "Lek_Disturbance_Modifier"
    CUMULATIVE_MODIFIER_PRE = "GRSG_Pre_Cumulative_Modifier"
    CUMULATIVE_MODIFIER_POST = "GRSG_Post_Cumulative_Modifier"
    CURRENT_ANTHRO_DISTURBANCE = "GRSG_Pre_Anthro_Disturbance"
    PROJECTED_ANTHRO_DISTURBANCE = "GRSG_Post_Anthro_Disturbance"
    GRSG_PRE_BREEDING = "GRSG_Pre_Breeding"
    GRSG_PRE_SUMMER = "GRSG_Pre_Summer"
    GRSG_PRE_WINTER = "GRSG_Pre_Winter"
    GRSG_POST_BREEDING = "GRSG_Post_Breeding"
    GRSG_POST_SUMMER = "GRSG_Post_Summer"
    GRSG_POST_WINTER = "GRSG_Post_Winter"
    # Mule Deer Filenames
    CURRENT_ANTHRO_DISTURBANCE_MD = "MuleDeer_Pre_Anthro_Disturbance"
    PROJECTED_ANTHRO_DISTURBANCE_MD = "MuleDeer_Post_Anthro_Disturbance"
    MULE_PRE_SUMMER = "MuleDeer_Pre_Summer"
    MULE_PRE_MIGRATION = "MuleDeer_Pre_Migration"
    MULE_PRE_WINTER = "MuleDeer_Pre_Winter"
    MULE_POST_SUMMER = "MuleDeer_Post_Summer"
    MULE_POST_MIGRATION = "MuleDeer_Post_Migration"
    MULE_POST_WINTER = "MuleDeer_Post_Winter"

    # ------------------------------------------------------------------------

    # FUNCTION CALLS
    # Check out Spatial Analyst extension
    hqtlib.CheckOutSpatialAnalyst()

    if not Proposed_Modified_Features_Provided:
        # Ensure Proposed_Modified_Features does not exist
        if arcpy.Exists("Proposed_Modified_Features"):
            arcpy.AddError("ERROR:: A 'Proposed_Modified_Features' layer "
                           "was detected in the project's geodatabase. "
                           "Provide the 'Proposed_Modified_Features' layer "
                           "and re-run Debit Tool 2.")
            sys.exit(0)

    # Clear selection, if present
    util.ClearSelectedFeatures(Proposed_Surface_Disturbance_Provided)

    # Check Proposed_Surface_Disturbance
    feature = Proposed_Surface_Disturbance_Provided
    required_fields = ["Type", "Subtype", "Surface_Disturbance"]
    no_null_fields = required_fields
    expected_fcs = None
    hqtlib.CheckPolygonInput(feature, required_fields, expected_fcs,
                             no_null_fields)

    # Update Proposed_Surface_Disturbance layer with provided layer
    provided_input = Proposed_Surface_Disturbance_Provided
    parameter_name = PROPOSED_SURFACE_DISTURBANCE_DEBITS
    Proposed_Surface_Disturbance = util.AdoptParameter(provided_input,
                                                       parameter_name,
                                                       preserve_existing=False)

    # Replace Proposed_Surface_Disturbance_Debits layer on map
    layerFile = cheStandard.getLayerFile("ProposedSurfaceDisturbance.lyr")
    util.AddToMap(Proposed_Surface_Disturbance, layerFile)

    # Add field for Disturbance_Type and populate. Values will be used in
    # Map_Units_Dissolve to identify map units of direct disturbance
    feature = Proposed_Surface_Disturbance
    fields = ["Disturbance_Type"]
    fieldTypes = ["TEXT"]
    util.AddFields(feature, fields, fieldTypes)

    with arcpy.da.UpdateCursor(feature,
                               ["Surface_Disturbance"] + fields) as cursor:
        for row in cursor:
            row[1] = "Direct_" + row[0]
            cursor.updateRow(row)

    # Update message
    arcpy.AddMessage("Creating the area of indirect impact")

    # Buffer proposed surface disturbance to create Indirect_Impact_Area
    in_data = Proposed_Surface_Disturbance
    out_name = INDIRECT_IMPACT_AREA
    Indirect_Impact_Area = hqtlib.CreateIndirectImpactArea(
        in_data, Parameter_Values, out_name)

    # Set up flag for projects that propose to modify anthro features
    includes_anthro_mod = False

    if Proposed_Modified_Features_Provided:
        # Update flag
        includes_anthro_mod = True

        # Clear selection, if present
        util.ClearSelectedFeatures(Proposed_Modified_Features_Provided)

        # Check provided layer
        required_fields = ["Type", "Subtype"]
        no_null_fields = required_fields
        expected_fcs = None
        hqtlib.CheckPolygonInput(Proposed_Modified_Features_Provided,
                                 required_fields, expected_fcs, no_null_fields)

        # Update Proposed_Modified_Features with provided layer and add to map
        provided_input = Proposed_Modified_Features_Provided
        parameterName = PROPOSED_MODIFIED_FEATURES
        preserve_existing = False
        Proposed_Modified_Features = util.AdoptParameter(
            provided_input, parameterName, preserve_existing)

        # Add Proposed Modified Features layer to map
        layerFile = cheStandard.getLayerFile("ProposedSurfaceDisturbance.lyr")
        util.AddToMap(Proposed_Modified_Features, layerFile)

        # Update message
        arcpy.AddMessage("Creating the area of indirect benefit")

        # Create the Indirect_Impact_Area
        in_data = Proposed_Modified_Features
        out_name = INDIRECT_BENEFIT_AREA
        Indirect_Benefit_Area = hqtlib.CreateIndirectImpactArea(
            in_data, Parameter_Values, out_name)

        # Union the indirect benefit area and the indirect impact area
        in_features = [Indirect_Impact_Area, Indirect_Benefit_Area]
        out_name = "in_memory/Impact_Union"
        Impact_Union = arcpy.Union_analysis(in_features, out_name)

        # Dissolve the unioned indirect impact and benefit areas as
        # Indirect Impact Area
        in_features = Impact_Union
        out_feature_class = INDIRECT_IMPACT_AREA
        Indirect_Impact_Area = arcpy.Dissolve_management(
            in_features, out_feature_class)

    # Detect habitat types impacted directly or indirectly
    is_grsg = cohqt.DetectHabitat(Indirect_Impact_Area, GrSG_Range)
    is_mule = cohqt.DetectHabitat(Indirect_Impact_Area, Mule_Range)

    # Update message
    arcpy.AddMessage("Determining project area - eliminating areas of non-"
                     "habitat from the Project Area")

    # Eliminate non-habitat
    project_area = Indirect_Impact_Area
    out_name = DEBIT_PROJECT_AREA
    Debit_Project_Area = hqtlib.EliminateNonHabitat(project_area, out_name,
                                                    habitat_bounds)

    # Calculate Area
    hqtlib.CalcAcres(Debit_Project_Area)

    # Add Debit Project Area to map
    feature = Debit_Project_Area
    layerFile = cheStandard.getLayerFile("DebitProjectArea.lyr")
    util.AddToMap(feature, layerFile, zoom_to=True)

    # Update message
    arcpy.AddMessage("Creating Analysis Area")

    # Create Analysis_Area
    out_name = ANALYSIS_AREA
    Analysis_Area = hqtlib.CreateAnalysisArea(Debit_Project_Area,
                                              Parameter_Values, out_name)

    # Add Analysis_Area to map
    layerFile = cheStandard.getLayerFile("AnalysisArea.lyr")
    util.AddToMap(Analysis_Area, layerFile, zoom_to=True)

    # Set processing extent to Analysis_Area
    arcpy.env.extent = ANALYSIS_AREA

    # Prepare proposed anthropogenic features
    unique_proposed_subtypes = cohqt.convertProposedToRasterDebit(
        Proposed_Surface_Disturbance, cellSize)

    anthroPath = cheStandard.AnthroFeaturePath
    cohqt.combineProposedWithCurrentDebit(anthroPath, unique_proposed_subtypes)

    # # Do something about anthropogenic mod features
    # if includes_anthro_mod:
    #     unique_proposed_subtypes_removed = hqtlib.convertProposedToRaster(
    #         Proposed_Modified_Features, cellSize
    #       )
    #
    #     anthroPath = cheStandard.AnthroFeaturePath
    #     hqtlib.combineProposedWithCurrent(anthroPath, unique_proposed_subtypes)

    ### GREATER SAGE-GROUSE ANTHRO DIST & MODIFIERS ###
    if is_grsg:
        # Update message
        arcpy.AddMessage("Calculating pre-project anthropogenic disturbance "
                         "modifier for greater sage-grouse")

        # Calculate pre-project anthropogenic disturbance
        dist_field = "GrSG_Dist"
        weight_field = "GrSG_Weight"
        term = cheStandard.DebitTerms[0]
        anthro_disturbance_type = "Pre"

        Current_Anthro_Disturbance = cohqt.CalcAnthroDisturbance(
            Parameter_Values, term, unique_proposed_subtypes,
            anthro_disturbance_type, cheStandard, dist_field, weight_field,
            cellSize, emptyRaster)
        Current_Anthro_Disturbance.save(CURRENT_ANTHRO_DISTURBANCE)

        # Update message
        arcpy.AddMessage("Current_Anthro_Disturbance Calculated")
        arcpy.AddMessage("Calculating post-project anthropogenic "
                         "disturbance modifier for greater sage-grouse")

        # Calculate post-project anthropogenic disturbance
        term = cheStandard.DebitTerms[1]
        anthro_disturbance_type = "Post"

        Projected_Anthro_Disturbance = cohqt.CalcAnthroDisturbance(
            Parameter_Values, term, unique_proposed_subtypes,
            anthro_disturbance_type, cheStandard, dist_field, weight_field,
            cellSize, emptyRaster)

        Projected_Anthro_Disturbance.save(PROJECTED_ANTHRO_DISTURBANCE)

        # Update message
        arcpy.AddMessage("Projected_Anthro_Disturbance Calculated")
        arcpy.AddMessage("Calculating lek disturbance modifier")

        # Calculate permanent anthropogenic disturbance

        # Calculate Lek Disturbance Modifier
        term = cheStandard.DebitTerms[1]
        anthro_disturbance_type = "LekDisturbanceModifier"

        Lek_Disturbance_Modifier = cohqt.CalcAnthroDisturbance(
            Parameter_Values, term, unique_proposed_subtypes,
            anthro_disturbance_type, cheStandard, dist_field, weight_field,
            cellSize, emptyRaster)

        Lek_Disturbance_Modifier.save(LEK_DISTURBANCE_MODIFIER)

        # Update message
        arcpy.AddMessage("Calculating Pre-Project Habitat Modifiers")

        # Calculate pre-project cumulative habitat modifiers
        winterHabitatPre = cohqt.calcWinterHabitatGRSG(
            Current_Anthro_Disturbance, ConiferModifier, GrSG_LDI, GrSGHabitat)
        LSDMWinterPre = cohqt.applyLekUpliftModifierPre(
            winterHabitatPre, LekPresenceRaster)
        breedingHabitatPre = cohqt.calcBreedingHabitatGRSG(
            Current_Anthro_Disturbance, ConiferModifier, GrSG_LDI,
            Lek_Distance_Modifier, GrSGHabitat)
        LSDMBreedingPre = cohqt.applyLekUpliftModifierPre(
            breedingHabitatPre, LekPresenceRaster)
        summerHabitatPre = cohqt.calcSummerHabitatGRSG(
            Current_Anthro_Disturbance, ConiferModifier, GrSG_LDI,
            SageModifier, GrSGHabitat)
        LSDMSummerPre = cohqt.applyLekUpliftModifierPre(
            summerHabitatPre, LekPresenceRaster)
        seasonalHabitatRasters = [
            LSDMWinterPre, LSDMBreedingPre, LSDMSummerPre
        ]

        # Save outputs
        # winterHabitatPre.save(GRSG_PRE_WINTER)
        LSDMWinterPre.save(GRSG_PRE_WINTER)
        # breedingHabitatPre.save(GRSG_PRE_BREEDING)
        LSDMBreedingPre.save(GRSG_PRE_BREEDING)
        # summerHabitatPre.save(GRSG_PRE_SUMMER)
        LSDMSummerPre.save(GRSG_PRE_SUMMER)

        # Calculate average of three seasonal habitat rasters pre-project
        finalPreCumulative = cohqt.calcAverageHabitatQuality(
            seasonalHabitatRasters)
        finalPreCumulative.save(CUMULATIVE_MODIFIER_PRE)

        # Calculate post-project cumulative habtiat modifiers
        winterHabitatPost = cohqt.calcWinterHabitatGRSG(
            Projected_Anthro_Disturbance, ConiferModifier, GrSG_LDI,
            GrSGHabitat)
        LSDMWinterPost = cohqt.applyLekUpliftModifierPost(
            winterHabitatPost, LekPresenceRaster, Lek_Disturbance_Modifier)
        breedingHabitatPost = cohqt.calcBreedingHabitatGRSG(
            Projected_Anthro_Disturbance, ConiferModifier, GrSG_LDI,
            Lek_Distance_Modifier, GrSGHabitat)
        LSDMBreedingPost = cohqt.applyLekUpliftModifierPost(
            breedingHabitatPost, LekPresenceRaster, Lek_Disturbance_Modifier)
        summerHabitatPost = cohqt.calcSummerHabitatGRSG(
            Projected_Anthro_Disturbance, ConiferModifier, GrSG_LDI,
            SageModifier, GrSGHabitat)
        LSDMSummerPost = cohqt.applyLekUpliftModifierPost(
            summerHabitatPost, LekPresenceRaster, Lek_Disturbance_Modifier)

        seasonalHabitatRasters = [
            LSDMWinterPost, LSDMBreedingPost, LSDMSummerPost
        ]

        # Save outputs
        # winterHabitatPost.save("Post_Seasonal_Winter")
        LSDMWinterPost.save(GRSG_POST_WINTER)
        # breedingHabitatPost.save("Post_Seasonal_Breeding")
        LSDMBreedingPost.save(GRSG_POST_BREEDING)
        # summerHabitatPost.save("Post_Seasonal_Summer")
        LSDMSummerPost.save(GRSG_POST_SUMMER)

        # Calculate average of three seasonal habitat rasters post-project
        finalPostCumulative = cohqt.calcAverageHabitatQuality(
            seasonalHabitatRasters)
        finalPostCumulative.save(CUMULATIVE_MODIFIER_POST)

        # Calculate permanent cumulative habtiat modifiers

        # Calculate Zonal Statistics for cumulative modifier rasters
        # Add field to use for zonal statistics
        inTable = Debit_Project_Area
        fields = ["ZONAL"]
        field_types = ["SHORT"]
        util.AddFields(inTable, fields, field_types)

        # Populate field with value 1
        arcpy.CalculateField_management(inTable, fields[0], 1, "PYTHON_9.3",
                                        "")

        # Update message
        arcpy.AddMessage("Calculating debits for greater sage-grouse")

        # Calculate zonal statistics for pre-project
        inZoneData = Debit_Project_Area
        inValueRaster = finalPreCumulative
        zoneField = fields[0]
        outTable = "GRSG_Stats_Pre"
        hqtlib.CalcZonalStats(inZoneData, zoneField, inValueRaster, outTable)

        # Join the zonal statistic to the Debit Project Area table
        fieldName = "GRSG_Pre_Project"
        hqtlib.JoinMeanToTable(inZoneData, outTable, zoneField, fieldName)

        # Calculate zonal statistics for post-project
        inZoneData = Debit_Project_Area
        inValueRaster = finalPostCumulative
        zoneField = fields[0]
        outTable = "GRSG_Stats_Post"
        hqtlib.CalcZonalStats(inZoneData, zoneField, inValueRaster, outTable)

        # Join the zonal statistic to the Debit Project Area table
        fieldName = "GrSG_Post_Project"
        hqtlib.JoinMeanToTable(inZoneData, outTable, zoneField, fieldName)

        # Calculate debits (if not collecting field data)
        cohqt.calcDebits(Debit_Project_Area, "GRSG_Pre_Project",
                         "GrSG_Post_Project", "Debits")

        # Update message
        arcpy.AddMessage("Creating visualization of impact from debit project")

        # Calculate impact intensity for debit project
        debit_impact = cohqt.calcImpact(finalPreCumulative,
                                        finalPostCumulative)
        debit_impact.save(DEBIT_PROJECT_IMPACT)

        # Add Debit Impact raster to map and save map document
        feature = debit_impact
        layerFile = cheStandard.getLayerFile("DebitProjectImpact.lyr")
        util.AddToMap(feature, layerFile, zoom_to=True)

    ### END GREATER SAGE-GROUSE ###

    ### MULE DEER ANTHRO DIST & MODIFIERS ###
    if not is_grsg:
        # Calculate Zonal Statistics for cumulative modifier rasters
        # Add field to use for zonal statistics
        inTable = Debit_Project_Area
        fields = ["ZONAL"]
        field_types = ["SHORT"]
        util.AddFields(inTable, fields, field_types)

        # Populate field with value 1
        arcpy.CalculateField_management(inTable, fields[0], 1, "PYTHON_9.3",
                                        "")

    # Update message
    if is_mule:
        arcpy.AddMessage("Calculating pre-project anthropogenic disturbance "
                         "modifier for mule deer")

        # Calculate pre-project anthropogenic disturbance
        # Calculate pre-project in PJ
        dist_field = "MDP_Dist"
        weight_field = "MDP_Weight"
        term = cheStandard.DebitTerms[0]
        #unique_proposed_subtypes = []
        anthro_disturbance_type = "Pre"

        anthro_pj = cohqt.CalcAnthroDisturbance(Parameter_Values, term,
                                                unique_proposed_subtypes,
                                                anthro_disturbance_type,
                                                cheStandard, dist_field,
                                                weight_field, cellSize,
                                                emptyRaster)
        anthro_pj.save(CURRENT_ANTHRO_DISTURBANCE_MD + "_P")

        # Calculate pre-project in Open
        dist_field = "MDO_Dist"
        weight_field = "MDO_Weight"
        term = cheStandard.DebitTerms[0]
        #unique_proposed_subtypes = []
        anthro_disturbance_type = "Pre"

        anthro_open = cohqt.CalcAnthroDisturbance(Parameter_Values,
                                                  term,
                                                  unique_proposed_subtypes,
                                                  anthro_disturbance_type,
                                                  cheStandard,
                                                  dist_field,
                                                  weight_field,
                                                  cellSize,
                                                  emptyRaster,
                                                  mask=BWMD_Open)
        anthro_open.save(CURRENT_ANTHRO_DISTURBANCE_MD + "_O")

        # Combine PJ and Open
        # If outside open, make 1
        anthro_open_only = Con(BWMD_Open == 1, anthro_open, 1)
        anthro_open_only.save(CURRENT_ANTHRO_DISTURBANCE_MD + "_OO")

        # Select minimum of pj and open rasters
        Current_Anthro_Disturbance = Con(anthro_open_only < anthro_pj,
                                         anthro_open_only, anthro_pj)
        Current_Anthro_Disturbance.save(CURRENT_ANTHRO_DISTURBANCE_MD)

        # Clean up
        arcpy.Delete_management("temp_masked_raster")
        # arcpy.Delete_management(CURRENT_ANTHRO_DISTURBANCE_MD + "_P")
        # arcpy.Delete_management(CURRENT_ANTHRO_DISTURBANCE_MD + "_O")
        # arcpy.Delete_management(CURRENT_ANTHRO_DISTURBANCE_MD + "_OO")

        # Update message
        arcpy.AddMessage("Current_Anthro_Disturbance Calculated")
        arcpy.AddMessage("Calculating post-project anthropogenic "
                         "disturbance modifier")

        # Calculate post-project anthropogenic disturbance
        # Calculate post-project in PJ
        dist_field = "MDP_Dist"
        weight_field = "MDP_Weight"
        term = cheStandard.DebitTerms[1]
        #unique_proposed_subtypes = []
        anthro_disturbance_type = "Post"

        anthro_pj = cohqt.CalcAnthroDisturbance(Parameter_Values, term,
                                                unique_proposed_subtypes,
                                                anthro_disturbance_type,
                                                cheStandard, dist_field,
                                                weight_field, cellSize,
                                                emptyRaster)
        anthro_pj.save(PROJECTED_ANTHRO_DISTURBANCE_MD + "_P")

        # Calculate pre-project in Open
        dist_field = "MDO_Dist"
        weight_field = "MDO_Weight"
        term = cheStandard.DebitTerms[1]
        #unique_proposed_subtypes = []
        anthro_disturbance_type = "Post"

        anthro_open = cohqt.CalcAnthroDisturbance(Parameter_Values,
                                                  term,
                                                  unique_proposed_subtypes,
                                                  anthro_disturbance_type,
                                                  cheStandard,
                                                  dist_field,
                                                  weight_field,
                                                  cellSize,
                                                  emptyRaster,
                                                  mask=BWMD_Open)
        anthro_open.save(PROJECTED_ANTHRO_DISTURBANCE_MD + "_O")

        # Combine PJ and Open
        # If outside open, make 1
        anthro_open_only = Con(BWMD_Open == 1, anthro_open, 1)
        anthro_open_only.save(PROJECTED_ANTHRO_DISTURBANCE_MD + "_OO")

        # Select minimum of pj and open rasters
        Projected_Anthro_Disturbance = Con(anthro_open_only < anthro_pj,
                                           anthro_open_only, anthro_pj)
        Projected_Anthro_Disturbance.save(PROJECTED_ANTHRO_DISTURBANCE_MD)

        # Update message
        arcpy.AddMessage("Projected_Anthro_Disturbance Calculated")
        # arcpy.AddMessage("Calculating lek disturbance modifier")
        #
        # # Calculate permanent anthropogenic disturbance
        #
        # # Calculate Lek Disturbance Modifier
        # term = cheStandard.CreditTerms[1]
        # anthro_disturbance_type = "LekDisturbanceModifier"
        #
        # Lek_Disturbance_Modifier = hqtlib.cheCalcAnthroDisturbance(
        #     Parameter_Values, term, unique_proposed_subtypes,
        #     anthro_disturbance_type, cheStandard, dist_field, weight_field,
        #     cellSize, emptyRaster
        # )
        #
        # Lek_Disturbance_Modifier.save(LEK_DISTURBANCE_MODIFIER)

        # Update message
        arcpy.AddMessage("Calculating Pre-Project Habitat Modifiers")

        # Calculate pre-project cumulative habitat modifiers
        summerHabitatPre = cohqt.calcSummerHabitatMD(
            Current_Anthro_Disturbance,
            MuleDeer_LDI,
            SummerModifier,
            SuitableHabitat=MuleDeerHabitat)
        # LSDMWinterPre = cohqt.applyLekUpliftModifierPre(summerHabitatPre,
        #                                                  LekPresenceRaster)
        migratoryHabitatPre = cohqt.calcMigratoryHabitatMD(
            Current_Anthro_Disturbance,
            MuleDeer_LDI,
            MigrationModifier,
            SuitableHabitat=MuleDeerHabitat)
        # LSDMBreedingPre = cohqt.applyLekUpliftModifierPre(migratoryHabitatPre,
        #                                                    LekPresenceRaster)
        winterHabitatPre = cohqt.calcWinterHabitatMD(
            Current_Anthro_Disturbance,
            MuleDeer_LDI,
            WinterModifier,
            SuitableHabitat=MuleDeerHabitat)
        # LSDMSummerPre = cohqt.applyLekUpliftModifierPre(winterHabitatPre,
        #                                                  LekPresenceRaster)
        seasonalHabitatRasters = [
            summerHabitatPre, migratoryHabitatPre, winterHabitatPre
        ]

        # Save outputs
        summerHabitatPre.save(MULE_PRE_SUMMER)
        # LSDMWinterPre.save("Pre_LSDM_Winter")
        migratoryHabitatPre.save(MULE_PRE_MIGRATION)
        # LSDMBreedingPre.save("Pre_LSDM_Breeding")
        winterHabitatPre.save(MULE_PRE_WINTER)
        # LSDMSummerPre.save("Pre_LSDM_Summer")

        # Calc zonal stats for pre-project modifiers (three seasons)
        term = cheStandard.DebitTerms[0]
        for season, raster in zip(cheStandard.MuleDeerSeasons,
                                  seasonalHabitatRasters):
            # Update message
            arcpy.AddMessage("Summarizing Mule Deer " + term + " " + season)

            # Calculate zonal statistics for each map unit
            inZoneData = Debit_Project_Area
            inValueRaster = raster
            zoneField = fields[0]
            outTable = "Mule_Stats_" + term + "_" + season
            hqtlib.CalcZonalStats(inZoneData, zoneField, inValueRaster,
                                  outTable)

            # Join the zonal statistic to the Map Units Dissolve table
            fieldName = "Mule_" + term + "_" + season
            hqtlib.JoinMeanToTable(inZoneData, outTable, zoneField, fieldName)

        # # Calculate average of three seasonal habitat rasters pre-project
        # finalPreCumulative = hqtlib.calcAverageHabitatQuality(
        #     seasonalHabitatRasters
        # )
        # finalPreCumulative.save(CUMULATIVE_MODIFIER_PRE)

        # Calculate post-project cumulative habitat modifiers
        summerHabitatPost = cohqt.calcSummerHabitatMD(
            Projected_Anthro_Disturbance,
            MuleDeer_LDI,
            SummerModifier,
            SuitableHabitat=MuleDeerHabitat)
        # LSDMWinterPost = cohqt.applyLekUpliftModifierPost(summerHabitatPost,
        #                                                  LekPresenceRaster)
        migratoryHabitatPost = cohqt.calcMigratoryHabitatMD(
            Projected_Anthro_Disturbance,
            MuleDeer_LDI,
            MigrationModifier,
            SuitableHabitat=MuleDeerHabitat)
        # LSDMBreedingPost = cohqt.applyLekUpliftModifierPost(migratoryHabitatPost,
        #                                                    LekPresenceRaster)
        winterHabitatPost = cohqt.calcWinterHabitatMD(
            Projected_Anthro_Disturbance,
            MuleDeer_LDI,
            WinterModifier,
            SuitableHabitat=MuleDeerHabitat)
        # LSDMSummerPost = cohqt.applyLekUpliftModifierPost(winterHabitatPost,
        #                                                  LekPresenceRaster)
        seasonalHabitatRasters = [
            summerHabitatPost, migratoryHabitatPost, winterHabitatPost
        ]

        # Save outputs
        summerHabitatPost.save(MULE_POST_SUMMER)
        # LSDMWinterPre.save("Pre_LSDM_Winter")
        migratoryHabitatPost.save(MULE_POST_MIGRATION)
        # LSDMBreedingPre.save("Pre_LSDM_Breeding")
        winterHabitatPost.save(MULE_POST_WINTER)
        # LSDMSummerPre.save("Pre_LSDM_Summer")

        # Calc zonal stats for pre-project modifiers (three seasons)
        term = cheStandard.DebitTerms[1]
        for season, raster in zip(cheStandard.MuleDeerSeasons,
                                  seasonalHabitatRasters):
            # Update message
            arcpy.AddMessage("Summarizing Mule Deer " + term + " " + season)

            # Calculate zonal statistics for each map unit
            inZoneData = Debit_Project_Area
            inValueRaster = raster
            zoneField = fields[0]
            outTable = "Mule_Stats_" + term + "_" + season
            hqtlib.CalcZonalStats(inZoneData, zoneField, inValueRaster,
                                  outTable)

            # Join the zonal statistic to the Map Units Dissolve table
            fieldName = "Mule_" + term + "_" + season
            hqtlib.JoinMeanToTable(inZoneData, outTable, zoneField, fieldName)

        # # Calculate average of three seasonal habitat rasters post-project
        # finalPostCumulative = hqtlib.calcAverageHabitatQuality(
        #     seasonalHabitatRasters
        # )
        # finalPostCumulative.save(CUMULATIVE_MODIFIER_POST)

        # Calculate permanent cumulative habtiat modifiers

        # Update message
        arcpy.AddMessage("Calculating Mule Deer Impact")

        # Calculate impact
        pre_fields = [
            "Mule_Pre_Summer", "Mule_Pre_Migration", "Mule_Pre_Winter"
        ]
        post_fields = [
            "Mule_Post_Summer", "Mule_Post_Migration", "Mule_Post_Winter"
        ]
        out_fields = [
            "Mule_Summer_Impact", "Mule_Migration_Impact", "Mule_Winter_Impact"
        ]
        for i in range(len(pre_fields)):
            pre_field = pre_fields[i]
            post_field = post_fields[i]
            out_field = out_fields[i]
            cohqt.calcDebits(Debit_Project_Area, pre_field, post_field,
                             out_field)

        # # Update message
        # arcpy.AddMessage("Creating visualization of impact from debit project")
        #
        # # Calculate impact intensity for debit project
        # debit_impact = hqtlib.calcImpact(finalPreCumulative, finalPostCumulative)
        # debit_impact.save(DEBIT_PROJECT_IMPACT)
        #
        # # Add Debit Impact raster to map and save map document
        # feature = debit_impact
        # layerFile = cheStandard.getLayerFile("DebitProjectImpact.lyr")
        # hqtlib.AddToMap(feature, layerFile, zoom_to=True)

        ### END MULE DEER ###

    if not is_grsg and not is_mule:
        arcpy.AddMessage("Impacts were not detected in any habitat type. "
                         "Please check credit project boundary and try "
                         "again")

    # Create Map_Units layer
    in_data = Debit_Project_Area
    out_data = MAP_UNITS
    Map_Units = hqtlib.CreateMapUnits(in_data, out_data)

    # Add Map_Units to map
    layerFile = cheStandard.getLayerFile("MapUnits.lyr")
    util.AddToMap(Map_Units, layerFile)

    # Add fields Map_Unit_ID, Map_Unit_Name, and Meadow to Map_Units
    fields = ["Map_Unit_ID", "Map_Unit_Name", "Notes", "Precip", "Transects"]
    fieldTypes = ["SHORT", "TEXT", "TEXT", "TEXT", "SHORT"]
    util.AddFields(Map_Units, fields, fieldTypes, copy_existing=True)

    # Add Domains to Map_Units layer
    # Create Domain for Map_Unit_ID attributes
    domainName = "Map_Unit_ID"
    range_low = 0
    range_high = 10000
    util.AddRangeDomain(Map_Units, projectGDB, domainName, range_low,
                        range_high)

    # Create Domain for Precip attributes
    feature_list = [Map_Units]
    domain_name = "Precip"
    code_list = ["Arid", "Mesic"]
    util.AddCodedTextDomain(feature_list, projectGDB, domain_name, code_list)

    # Update message
    arcpy.AddMessage("Cleaning up workspace")

    # Clean up
    for raster in arcpy.ListRasters("*_Subtype_Disturbance"):
        arcpy.Delete_management(raster)

    for raster in arcpy.ListRasters("*_Type_Disturbance"):
        arcpy.Delete_management(raster)

    arcpy.Delete_management("in_memory")
    try:
        arcpy.Delete_management(scratch_folder)
    except:
        pass

    # Save map document and exit
    if arcpy.ListInstallations()[0] == 'arcgispro':
        p = arcpy.mp.ArcGISProject("CURRENT")
        p.save()
    else:
        mxd = arcpy.mapping.MapDocument("CURRENT")
        mxd.save()
Example #18
0
def CalcAnthroDisturbance(Parameter_Values, term, unique_proposed_subtypes,
                             anthro_disturbance_type, cheStandard,
                             dist_field, weight_field, cellSize, emptyRaster,
                             mask = None):
    """
    Calculates the anthropogenic disturbance associated with all subtypes of
    disturbance present within the Analysis Area, selects the maximum impact
    for all subtypes within each type and then multiplies those to
    calculate cumulative anthropogenic disturbance and saves to the project's
    gdb.
    :param cellSize:
    :param Anthro_Features: feature class with anthropogenic features
    :param raster_100: raster of value 100
    :param Analysis_Area: Analysis Area feature class
    :param Parameter_Values: the Parameter Values table
    :param term: string corresponding to term
    :param field: field name where Subtype is stored as a string
    :return: the name of the resulting anthropogenic disturbance raster as
    a string
    """
    # Extract lists of Types, Subtypes, Distances, and Weights
    typeList = [row[0] for row in arcpy.da.SearchCursor(
        Parameter_Values, "Type")]
    subtypeList = [row[0] for row in arcpy.da.SearchCursor(
        Parameter_Values, "Subtype")]
    distanceList = [row[0] for row in arcpy.da.SearchCursor(
        Parameter_Values, dist_field)]
    weightList = [row[0] for row in arcpy.da.SearchCursor(
        Parameter_Values, weight_field)]

    # Create dictionaries for weights and distances by subtype
    distanceDict = dict(list(zip(subtypeList, distanceList)))
    weightDict = dict(list(zip(subtypeList, weightList)))

    # Identify raster that will be used as the snap raster
    arcpy.env.snapRaster = emptyRaster

    def makeUnique(typeList):
        """Uniquify the anthropogenic feature types"""
        uniqueTypes = []
        for anthroType in typeList:
            if anthroType not in uniqueTypes:
                if anthroType != "N/A":
                    uniqueTypes.append(anthroType)
        return uniqueTypes

    def getUniqueSubtypes(uniqueType, typeList, subtypeList):
        """get unique subtypes associated with each type"""
        uniqueSubtypeList = []
        i = 0
        for t in typeList:
            if t == uniqueType:
                subtypeIndex = i
                subtype = subtypeList[subtypeIndex]
                uniqueSubtypeList.append(subtype)
            i += 1
        return uniqueSubtypeList

    def calcSubtypeDisturbance(AnthroFeatures, subtype, AnthroDisturbanceType):
        """calculate disturbance associated with each subtype"""
        distance = distanceDict[subtype]
        weight = weightDict[subtype]

        AnthroFeatures = Raster(AnthroFeatures)

        if distance > 0:
            arcpy.AddMessage("  Calculating direct and indirect effects of "
                             + str(subtype))
            outEucDist = EucDistance(AnthroFeatures, distance, cellSize)
            tmp1 = 100 - (1/(1 + Exp(((outEucDist / (distance/2))-1)*5))) * weight  # sigmoidal
            # tmp1 = (100 - (weight * Power((1 - outEucDist/distance), 2)))  # exponential
            # tmp1 = 100 - (weight - (outEucDist / distance) * weight)  # linear
            tmp2 = Con(IsNull(tmp1), 100, tmp1)
            subtypeRaster = tmp2
            subtypeRaster.save(AnthroDisturbanceType + "_" + subtype
                               + "_Subtype_Disturbance")
        elif weight > 0:
            arcpy.AddMessage("  Calculating direct effects of "
                             + str(subtype))
            tmp3 = Con(IsNull(AnthroFeatures), 0, AnthroFeatures)
            subtypeRaster = 100 - (tmp3 * weight)
            subtypeRaster.save(AnthroDisturbanceType + "_" + subtype
                               + "_Subtype_Disturbance")
        else:
            subtypeRaster = None

        return subtypeRaster

    def calcTypeDisturbance(anthroType, subtypeRasters, AnthroDisturbanceType):
        """combine anthropogenic disturbance for all subtypes of a specific type"""
        arcpy.AddMessage("   Combining effects of "
                         + str(anthroType) + " features")
        typeRaster100 = CellStatistics(subtypeRasters, "MINIMUM")
        typeRaster = typeRaster100 / 100
        typeRaster.save(AnthroDisturbanceType + "_" + anthroType
                        + "_Type_Disturbance")

        return typeRaster

    def multiplyRasters(rasterList, AnthroDisturbanceType, emptyRaster):
        """multiply type rasters to calculate overall disturbance"""
        # Define local variables
        Agriculture_Index = cheStandard.AgricultureIndex
        # Urban_Index = cheStandard.UrbanIndex
        Lakes = cheStandard.Lakes

        if AnthroDisturbanceType == "Pre" or AnthroDisturbanceType == "Post":
            if dist_field == "GrSG_Dist":  # better way of distinguishing if ag index needed
                rasterList2 = rasterList + [Agriculture_Index, Lakes]
            else:
                rasterList2 = rasterList + [Lakes]
            anthroRaster = np.prod(np.array(rasterList2))
        elif AnthroDisturbanceType == "LekDisturbanceModifier":
            rasterList2 = rasterList + [emptyRaster]
            anthroRaster = np.prod(np.array(rasterList2))

        return anthroRaster

    # Function calls
    anthro_path = cheStandard.AnthroFeaturePath
    uniqueTypes = makeUnique(typeList)
    rasterList = []
    # features = arcpy.MakeFeatureLayer_management(Anthro_Features, "lyr")
    for anthroType in uniqueTypes:
        arcpy.AddMessage(" Evaluating " + term + " "
                         + anthroType + " Indirect Disturbance")
        uniqueSubtypeList = getUniqueSubtypes(anthroType, typeList, subtypeList)
        subtypeRasters = []
        for subtype in uniqueSubtypeList:
            # where_clause = """{} = '{}'""".format(
            #     arcpy.AddFieldDelimiters(features, field), subtype)
            # arcpy.SelectLayerByAttribute_management(features, "NEW_SELECTION",
            #                                         where_clause)
            #
            # test = arcpy.GetCount_management(features)
            # count = int(test.getOutput(0))
            # # arcpy.AddMessage("   " + str(count) + " features found of subtype " +
            # #                  subtype)
            #
            # if count > 0:
            #     # Convert selected anthro features to raster to prevent losing
            #     # small features that do not align with cell centers
            #     arcpy.AddMessage("   Features detected of subtype " + subtype)
            #     AddFields(features, ["raster"], ["SHORT"])
            #     with arcpy.da.UpdateCursor(features, ["raster"]) as cursor:
            #         for row in cursor:
            #             row[0] = 1
            #             cursor.updateRow(row)
            #     value_field = "raster"
            #     out_rasterdataset = "in_memory/tmp_raster"
            #     cell_assignment = "MAXIMUM_AREA"
            #     priority_field = "raster"
            #     cellSize = arcpy.GetRasterProperties_management(
            #         raster_100, "CELLSIZEX").getOutput(0)
            #     arcpy.PolygonToRaster_conversion(features,
            #                                      value_field,
            #                                      out_rasterdataset,
            #                                      cell_assignment,
            #                                      priority_field,
            #                                      cellSize)
            #     arcpy.DeleteField_management(features, "raster")

            # Determine which anthro features rasters to use depending
            # on anthropogenic disturbance type being calculated ('pre',
            # 'post', or 'LekDisturbanceModifier')

            # For calculating pre-project anthro disturbance
            if anthro_disturbance_type == "Pre":
                AnthroFeatures = os.path.join(anthro_path, subtype)

            # For calculating post-project anthro disturbance
            elif anthro_disturbance_type == "Post":
                if subtype in unique_proposed_subtypes:
                    AnthroFeatures = "Post_" + subtype
                else:
                    AnthroFeatures = os.path.join(anthro_path, subtype)

            # For calculating Lek Disturbance Modifier
            elif anthro_disturbance_type == "LekDisturbanceModifier":
                if subtype in unique_proposed_subtypes:
                    AnthroFeatures = "Proposed_" + subtype
                else:
                    AnthroFeatures = None

            # For each subtype, calculate subtype raster
            if AnthroFeatures is not None:
                # Mask out anthro features if specified
                if mask is not None:
                    AnthroFeatures2 = Con(mask == 0, AnthroFeatures, None)
                    AnthroFeatures2.save("temp_masked_raster")
                    # AnthroFeatures = "temp_masked_raster"
                    # Calculate statistics to avoid table not found error
                    try:
                        AnthroFeatures = arcpy.CalculateStatistics_management(
                            "temp_masked_raster"
                        )
                        subtypeRaster = calcSubtypeDisturbance("temp_masked_raster",
                                                               subtype,
                                                               term)
                    except arcpy.ExecuteError:
                        subtypeRaster = None
                else:
                    subtypeRaster = calcSubtypeDisturbance(AnthroFeatures,
                                                           subtype,
                                                           term)
                if subtypeRaster is not None:
                    subtypeRasters.append(subtypeRaster)

        # For each type, combine subtype rasters to calculate type raster
        if len(subtypeRasters) > 0:
            typeRaster = calcTypeDisturbance(anthroType, subtypeRasters,
                                             term)
            rasterList.append(typeRaster)

    # Calculate combined anthropogenic disturbance raster
    anthroRaster = multiplyRasters(rasterList, anthro_disturbance_type,
                                   emptyRaster)

    # Clean up
    arcpy.Delete_management("in_memory")

    return anthroRaster
Example #19
0
def convertProposedToRasterCredit(anthroFeaturesRemoved, cellSize):
    arcpy.AddMessage("Preparing Proposed Surface Disturbance for processing")
    # Add field Conifer to use when converting to raster
    inTable = anthroFeaturesRemoved
    fieldName = "Weight2"
    fieldType = "SHORT"
    expression = 1
    arcpy.AddField_management(inTable, fieldName, fieldType)
    arcpy.CalculateField_management(inTable, fieldName, expression, "PYTHON_9.3", "")

    # Check feature type of provided feature class
    desc = arcpy.Describe(anthroFeaturesRemoved)

    # Make feature layer of proposed surface disturbance
    features = arcpy.MakeFeatureLayer_management(anthroFeaturesRemoved, "lyr")

    # Generate list of unique subtypes in Proposed_Surface_Disturbance
    uniqueProposedSubtypes = list(set([row[0] for row in arcpy.da.SearchCursor(
        anthroFeaturesRemoved, "Subtype")]))
    arcpy.AddMessage("Proposed Surface Disturbance contains "
                     + ", ".join(uniqueProposedSubtypes))

    for subtype in uniqueProposedSubtypes:
        # Select features of specified subtype
        field = "Subtype"
        where_clause = """{} = '{}'""".format(arcpy.AddFieldDelimiters
                                              (features, field), subtype)

        arcpy.SelectLayerByAttribute_management(features,
                                                "NEW_SELECTION",
                                                where_clause)

        # Count features selected to ensure >0 feature selected
        test = arcpy.GetCount_management(features)
        count = int(test.getOutput(0))

        # Convert to raster
        if count > 0:
            in_features = features
            value_field = "Weight"
            out_rasterdataset = os.path.join("in_memory", "Proposed_" + subtype + "Null")
            cell_assignment = "MAXIMUM_AREA"
            priority_field = "Weight"

            if desc.shapeType == "Polygon":
                arcpy.PolygonToRaster_conversion(in_features,
                                                 value_field,
                                                 out_rasterdataset,
                                                 cell_assignment,
                                                 priority_field,
                                                 cellSize)
            else:  # Consider changing to buffer of ? meters
                arcpy.FeatureToRaster_conversion(in_features,
                                                 value_field,
                                                 out_rasterdataset,
                                                 cellSize)

            # Change Null values to 0 in proposed anthro feature removed raster
            out_con = Con(IsNull(out_rasterdataset), 0, out_rasterdataset)
            out_con.save("Proposed_" + subtype)

        # Clear selected features
        arcpy.SelectLayerByAttribute_management(features, "CLEAR_SELECTION")

    return uniqueProposedSubtypes
Example #20
0
def main():
    # GET PARAMETER VALUES
    Map_Units_Provided = arcpy.GetParameterAsText(0)

    # DEFINE DIRECTORIES
    # Get the pathname to this script
    scriptPath = sys.path[0]
    arcpy.AddMessage("Script folder: " + scriptPath)
    arcpy.AddMessage("Python version: " + sys.version)
    # Construct pathname to workspace
    projectGDB = arcpy.Describe(Map_Units_Provided).path
    arcpy.AddMessage("Project geodatabase: " + projectGDB)

    # Instantiate a idStandard object
    cheStandard = cohqt.cheStandard(projectGDB, scriptPath)

    # ENVIRONMENT SETTINGS
    # Set workspaces
    arcpy.env.workspace = projectGDB
    scratch_folder = os.path.join(arcpy.Describe(projectGDB).path, 'scratch')
    if arcpy.Exists(scratch_folder):
        pass
    else:
        arcpy.CreateFolder_management(scratch_folder)
    arcpy.env.scratchWorkspace = scratch_folder
    # Overwrite outputs
    arcpy.env.overwriteOutput = True

    # DEFINE GLOBAL VARIABLES
    cell_size = 30
    inputDataPath = cheStandard.InputDataPath
    GrSG_Habitat = cheStandard.GrSGHabitatRaster
    ConiferModifier = cheStandard.ConiferModifier
    GrSG_LDI = cheStandard.GrSG_LDI
    LekPresenceRaster = cheStandard.LekPresenceRaster
    Lek_Distance_Modifier = cheStandard.LekDistanceModifier
    SageModifier = cheStandard.SageModifier
    GrSG_Habitat = cheStandard.BWSGHab

    # Filenames of feature classes and rasters used by this script
    MAP_UNITS = "Map_Units"
    PROPOSED_SURFACE_DISTURBANCE_DEBITS = "Proposed_Surface_Disturbance_Debits"
    DISTURBED_FOOTPRINT = "Disturbed_Footprint"
    CURRENT_ANTHRO_FEATURES = "Current_Anthro_Features"
    CURRENT_ANTHRO_DISTURBANCE = "GrSG_Pre_Anthro_Disturbance"
    PROJECTED_ANTHRO_DISTURBANCE = "GRSG_Post_Anthro_Disturbance"
    LEK_DISTURBANCE_MODIFIER = "Lek_Disturbance_Modifier"
    DEBIT_PROJECT_AREA = "Debit_Project_Area"
    DEBIT_PROJECT_IMPACT_A = "Debit_Project_Impact_Adjusted"

    # Filenames of feature classes and rasters created by this script
    # GrSG Filenames
    GRSG_PRE_BREEDING_A = "GRSG_Pre_Breeding_adjusted"
    GRSG_PRE_SUMMER_A = "GRSG_Pre_Summer_adjusted"
    GRSG_PRE_WINTER_A = "GRSG_Pre_Winter_adjusted"
    GRSG_POST_BREEDING_A = "GRSG_Post_Breeding_adjusted"
    GRSG_POST_SUMMER_A = "GRSG_Post_Summer_adjusted"
    GRSG_POST_WINTER_A = "GRSG_Post_Winter_adjusted"
    CUMULATIVE_MODIFIER_PRE_A = "GRSG_Pre_Cumulative_Modifier_adjusted"
    CUMULATIVE_MODIFIER_POST_A = "GRSG_Post_Cumulative_Modifier_adjusted"

    # ------------------------------------------------------------------------

    # FUNCTION CALLS
    # Check out Spatial Analyst extension
    hqtlib.CheckOutSpatialAnalyst()

    # Clear selection, if present
    util.ClearSelectedFeatures(Map_Units_Provided)

    # Check Map_Units layer
    feature = Map_Units_Provided
    required_fields = ["Map_Unit_ID", "Map_Unit_Name"]
    no_null_fields = ["Map_Unit_ID"]
    expected_fcs = None
    hqtlib.CheckPolygonInput(feature, required_fields, expected_fcs,
                             no_null_fields)

    # Update Map Units layer with provided layer and add to map
    Map_Units = util.AdoptParameter(Map_Units_Provided,
                                    MAP_UNITS,
                                    preserve_existing=False)
    layerFile = cheStandard.getLayerFile("MapUnits.lyr")
    util.AddToMap(Map_Units, layerFile)

    # # Udpate message
    # arcpy.AddMessage("Dissolving all multi-part map units to create "
    #                  "Map_Units_Dissolve")

    # # Dissolve Map Units
    # allowable_fields = ["Map_Unit_ID", "Map_Unit_Name", "Notes",
    #                     "Disturbance_Type", "Precip", ]
    # out_name = MAP_UNITS_DISSOLVE
    # anthro_features = CURRENT_ANTHRO_FEATURES
    # Map_Units_Dissolve = hqtlib.DissolveMapUnits(MUs, allowable_fields,
    #                                             out_name, anthro_features)

    # # Update message
    # arcpy.AddMessage("Adding Map_Units_Dissolve to map")

    # # Add layer to map document
    # feature = Map_Units_Dissolve
    # layerFile = cheStandard.getLayerFile("Map_Units.lyr")
    # util.AddToMap(feature, layerFile)

    # # Update message
    # arcpy.AddMessage("Calculating area in acres for each map unit")

    # # Calculate Area
    # hqtlib.CalcAcres(Map_Units_Dissolve)

    # Update message
    arcpy.AddMessage("Creating site-scale habitat quality rasters")

    # # ADD Join from Excel Doc
    # out_table = os.path.join(projectGDB, "Site_Scale_Scores")
    # summary_table = arcpy.ExcelToTable_conversion(Debit_Calculator,
    #                                               out_table,
    #                                               "Summary")

    # arcpy.AddJoin_management(Map_Units, "Map_Unit_ID",
    #                          summary_table, "MapUnitID")

    # Convert Map Units to raster of Habitat Quality (0 - 1 scale) and  mask
    # out BWSG habitat
    seasonsList = cheStandard.GrSGSeasons
    for season in seasonsList:
        mu_raster_path = cohqt.convertMapUnitsToRaster(projectGDB, Map_Units,
                                                       season, cell_size)
        mu_raster = Raster(mu_raster_path)
        # Mask out BWSG habitat
        SuitableHabitat_adjusted = Con(IsNull(Float(mu_raster)), GrSG_Habitat,
                                       Float(mu_raster))
        SuitableHabitat_adjusted.save(
            os.path.join(projectGDB, season + "_Habitat_adjusted"))

    # Update message
    arcpy.AddMessage("Calculating Pre-Project Habitat Modifiers")

    # Re-run fron calcWinterHabitat down with updated BWSG layer (append
    # "_adjusted")

    WinterSuitableHabitat = os.path.join(projectGDB, "Winter_Habitat_adjusted")
    winterHabitatPre = cohqt.calcWinterHabitatGRSG(CURRENT_ANTHRO_DISTURBANCE,
                                                   ConiferModifier, GrSG_LDI,
                                                   WinterSuitableHabitat)
    LSDMWinterPre = cohqt.applyLekUpliftModifierPre(winterHabitatPre,
                                                    LekPresenceRaster)

    BreedingSuitableHabitat = os.path.join(projectGDB,
                                           "Breed_Habitat_adjusted")
    breedingHabitatPre = cohqt.calcBreedingHabitatGRSG(
        CURRENT_ANTHRO_DISTURBANCE, ConiferModifier, GrSG_LDI,
        Lek_Distance_Modifier, BreedingSuitableHabitat)
    LSDMBreedingPre = cohqt.applyLekUpliftModifierPre(breedingHabitatPre,
                                                      LekPresenceRaster)

    SummerSuitableHabitat = os.path.join(projectGDB, "Summer_Habitat_adjusted")
    summerHabitatPre = cohqt.calcSummerHabitatGRSG(CURRENT_ANTHRO_DISTURBANCE,
                                                   ConiferModifier, GrSG_LDI,
                                                   SageModifier,
                                                   SummerSuitableHabitat)
    LSDMSummerPre = cohqt.applyLekUpliftModifierPre(summerHabitatPre,
                                                    LekPresenceRaster)

    seasonalHabitatRasters = [LSDMWinterPre, LSDMBreedingPre, LSDMSummerPre]

    # Save outputs
    # winterHabitatPre.save("Pre_Seasonal_Winter_adjusted")
    LSDMWinterPre.save(GRSG_PRE_WINTER_A)
    # breedingHabitatPre.save("Pre_Seasonal_Breeding_adjusted")
    LSDMBreedingPre.save(GRSG_PRE_BREEDING_A)
    # summerHabitatPre.save("Pre_Seasonal_Summer_adjusted")
    LSDMSummerPre.save(GRSG_PRE_SUMMER_A)

    # Calculate average of three seasonal habitat rasters pre-project
    finalPreCumulative = cohqt.calcAverageHabitatQuality(
        seasonalHabitatRasters)
    finalPreCumulative.save(CUMULATIVE_MODIFIER_PRE_A)

    # Calculate post-project cumulative habtiat modifiers
    winterHabitatPost = cohqt.calcWinterHabitatGRSG(
        PROJECTED_ANTHRO_DISTURBANCE, ConiferModifier, GrSG_LDI,
        WinterSuitableHabitat)
    LSDMWinterPost = cohqt.applyLekUpliftModifierPost(
        winterHabitatPost, LekPresenceRaster, LEK_DISTURBANCE_MODIFIER)
    breedingHabitatPost = cohqt.calcBreedingHabitatGRSG(
        PROJECTED_ANTHRO_DISTURBANCE, ConiferModifier, GrSG_LDI,
        Lek_Distance_Modifier, BreedingSuitableHabitat)
    LSDMBreedingPost = cohqt.applyLekUpliftModifierPost(
        breedingHabitatPost, LekPresenceRaster, LEK_DISTURBANCE_MODIFIER)
    summerHabitatPost = cohqt.calcSummerHabitatGRSG(
        PROJECTED_ANTHRO_DISTURBANCE, ConiferModifier, GrSG_LDI, SageModifier,
        SummerSuitableHabitat)
    LSDMSummerPost = cohqt.applyLekUpliftModifierPost(
        summerHabitatPost, LekPresenceRaster, LEK_DISTURBANCE_MODIFIER)

    seasonalHabitatRasters = [LSDMWinterPost, LSDMBreedingPost, LSDMSummerPost]

    # Save outputs
    # winterHabitatPost.save("Post_Seasonal_Winter")
    LSDMWinterPost.save(GRSG_POST_WINTER_A)
    # breedingHabitatPost.save("Post_Seasonal_Breeding")
    LSDMBreedingPost.save(GRSG_POST_BREEDING_A)
    # summerHabitatPost.save("Post_Seasonal_Summer")
    LSDMSummerPost.save(GRSG_POST_SUMMER_A)

    # Calculate average of three seasonal habitat rasters post-project
    finalPostCumulative = cohqt.calcAverageHabitatQuality(
        seasonalHabitatRasters)
    finalPostCumulative.save(CUMULATIVE_MODIFIER_POST_A)

    # Calculate Zonal Statistics for cumulative modifier rasters
    # Calculate zonal statistics for pre-project
    inZoneData = DEBIT_PROJECT_AREA
    inValueRaster = finalPreCumulative
    zoneField = "ZONAL"
    outTable = "GRSG_Stats_Pre_adjusted"
    hqtlib.CalcZonalStats(inZoneData, zoneField, inValueRaster, outTable)

    # Join the zonal statistic to the Debit Project Area table
    fieldName = "GRSG_Pre_Project_A"
    hqtlib.JoinMeanToTable(inZoneData, outTable, zoneField, fieldName)

    # Calculate zonal statistics for post-project
    inZoneData = DEBIT_PROJECT_AREA
    inValueRaster = finalPostCumulative
    zoneField = "ZONAL"
    outTable = "GRSG_Stats_Post_adjusted"
    hqtlib.CalcZonalStats(inZoneData, zoneField, inValueRaster, outTable)

    # Join the zonal statistic to the Debit Project Area table
    fieldName = "GrSG_Post_Project_A"
    hqtlib.JoinMeanToTable(inZoneData, outTable, zoneField, fieldName)

    # Calculate debits using field data
    cohqt.calcDebits(DEBIT_PROJECT_AREA, "GRSG_Pre_Project_A",
                     "GrSG_Post_Project_A", "Debits_adj")

    # Update message
    arcpy.AddMessage("Creating visualization of impact from debit project")

    # Calculate impact intensity for debit project
    debit_impact = cohqt.calcImpact(finalPreCumulative, finalPostCumulative)
    debit_impact.save(DEBIT_PROJECT_IMPACT_A)

    # Add Debit Impact raster to map and save map document
    feature = debit_impact
    layerFile = cheStandard.getLayerFile("DebitProjectImpact.lyr")
    util.AddToMap(feature, layerFile, zoom_to=True)

    # Clean up
    arcpy.Delete_management("in_memory")

    # Save map document
    if arcpy.ListInstallations()[0] == 'arcgispro':
        p = arcpy.mp.ArcGISProject("CURRENT")
        p.save()
    else:
        mxd = arcpy.mapping.MapDocument("CURRENT")
        mxd.save()