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)
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))
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
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)
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))
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
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()
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")
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')
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
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')
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
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
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')
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()
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
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
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()