def derive_from_dem(dem): """derive slope and flow direction from a DEM. Results are returned in a dictionary that contains references to ArcPy Raster objects stored in the "in_memory" (temporary) workspace """ # set the snap raster for subsequent operations env.snapRaster = dem # calculate flow direction for the whole DEM flowdir = FlowDirection(in_surface_raster=dem, force_flow="NORMAL") flow_direction_raster = so("flowdir", "random", "in_memory") flowdir.save(flow_direction_raster) # calculate slope for the whole DEM slope = Slope(in_raster=dem, output_measurement="PERCENT_RISE", method="PLANAR") slope_raster = so("slope", "random", "in_memory") slope.save(slope_raster) return { "flow_direction_raster": Raster(flow_direction_raster), "slope_raster": Raster(slope_raster), }
def function(outputFolder, DEM, studyAreaMask, streamInput, minAccThresh, majAccThresh, smoothDropBuffer, smoothDrop, streamDrop, reconDEM, rerun=False): try: # Set environment variables arcpy.env.compression = "None" arcpy.env.snapRaster = DEM arcpy.env.extent = DEM arcpy.env.cellSize = arcpy.Describe(DEM).meanCellWidth ######################## ### Define filenames ### ######################## files = common.getFilenames('preprocess', outputFolder) rawDEM = files.rawDEM hydDEM = files.hydDEM hydFDR = files.hydFDR hydFDRDegrees = files.hydFDRDegrees hydFAC = files.hydFAC streamInvRas = files.streamInvRas # Inverse stream raster - 0 for stream, 1 for no stream streams = files.streams streamDisplay = files.streamDisplay multRaster = files.multRaster hydFACInt = files.hydFACInt slopeRawDeg = files.slopeRawDeg slopeRawPer = files.slopeRawPer slopeHydDeg = files.slopeHydDeg slopeHydPer = files.slopeHydPer ############################### ### Set temporary variables ### ############################### prefix = os.path.join(arcpy.env.scratchGDB, "base_") cellSizeDEM = float(arcpy.env.cellSize) burnedDEM = prefix + "burnedDEM" streamAccHaFile = prefix + "streamAccHa" rawFDR = prefix + "rawFDR" allPolygonSinks = prefix + "allPolygonSinks" DEMTemp = prefix + "DEMTemp" hydFACTemp = prefix + "hydFACTemp" # Saved as .tif as did not save as ESRI grid on server streamsRasterFile = os.path.join(arcpy.env.scratchFolder, "base_") + "StreamsRaster.tif" ############################### ### Save DEM to base folder ### ############################### codeBlock = 'Save DEM' if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun): # Save DEM to base folder as raw DEM with no compression pixelType = int( arcpy.GetRasterProperties_management(DEM, "VALUETYPE").getOutput(0)) if pixelType == 9: # 32 bit float arcpy.CopyRaster_management(DEM, rawDEM, pixel_type="32_BIT_FLOAT") else: log.info("Converting DEM to 32 bit floating type") arcpy.CopyRaster_management(DEM, DEMTemp) arcpy.CopyRaster_management(Float(DEMTemp), rawDEM, pixel_type="32_BIT_FLOAT") # Delete temporary DEM arcpy.Delete_management(DEMTemp) # Calculate statistics for raw DEM arcpy.CalculateStatistics_management(rawDEM) progress.logProgress(codeBlock, outputFolder) ################################ ### Create multiplier raster ### ################################ codeBlock = 'Create multiplier raster' if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun): Reclassify(rawDEM, "Value", RemapRange([[-999999.9, 999999.9, 1]]), "NODATA").save(multRaster) progress.logProgress(codeBlock, outputFolder) codeBlock = 'Calculate slope in percent' if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun): intSlopeRawPer = Slope(rawDEM, "PERCENT_RISE") intSlopeRawPer.save(slopeRawPer) del intSlopeRawPer log.info('Slope calculated in percent') progress.logProgress(codeBlock, outputFolder) if reconDEM is True: ####################### ### Burn in streams ### ####################### codeBlock = 'Burn in streams' if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun): # Recondition DEM (burning stream network in using AGREE method) log.info("Burning streams into DEM.") reconditionDEM.function(rawDEM, streamInput, smoothDropBuffer, smoothDrop, streamDrop, burnedDEM) log.info("Completed stream network burn in to DEM") progress.logProgress(codeBlock, outputFolder) ################## ### Fill sinks ### ################## codeBlock = 'Fill sinks' if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun): Fill(burnedDEM).save(hydDEM) log.info("Sinks in DEM filled") progress.logProgress(codeBlock, outputFolder) ###################### ### Flow direction ### ###################### codeBlock = 'Flow direction' if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun): FlowDirection(hydDEM, "NORMAL").save(hydFDR) log.info("Flow Direction calculated") progress.logProgress(codeBlock, outputFolder) ################################# ### Flow direction in degrees ### ################################# codeBlock = 'Flow direction in degrees' if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun): # Save flow direction raster in degrees (for display purposes) degreeValues = RemapValue([[1, 90], [2, 135], [4, 180], [8, 225], [16, 270], [32, 315], [64, 0], [128, 45]]) Reclassify(hydFDR, "Value", degreeValues, "NODATA").save(hydFDRDegrees) progress.logProgress(codeBlock, outputFolder) ######################### ### Flow accumulation ### ######################### codeBlock = 'Flow accumulation' if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun): hydFACTemp = FlowAccumulation(hydFDR, "", "FLOAT") hydFACTemp.save(hydFAC) arcpy.sa.Int(Raster(hydFAC)).save(hydFACInt) # integer version log.info("Flow Accumulation calculated") progress.logProgress(codeBlock, outputFolder) ####################### ### Calculate slope ### ####################### codeBlock = 'Calculate slope on burned DEM' if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun): intSlopeHydDeg = Slope(hydDEM, "DEGREE") intSlopeHydDeg.save(slopeHydDeg) del intSlopeHydDeg intSlopeHydPer = Slope(hydDEM, "PERCENT_RISE") intSlopeHydPer.save(slopeHydPer) del intSlopeHydPer log.info('Slope calculated') progress.logProgress(codeBlock, outputFolder) ########################## ### Create stream file ### ########################## codeBlock = 'Create stream file' if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun): # Create accumulation in metres streamAccHaFileInt = hydFACTemp * cellSizeDEM * cellSizeDEM / 10000.0 streamAccHaFileInt.save(streamAccHaFile) del streamAccHaFileInt # Check stream initiation threshold reached streamYes = float( arcpy.GetRasterProperties_management( streamAccHaFile, "MAXIMUM").getOutput(0)) if streamYes > float(minAccThresh): reclassifyRanges = RemapRange( [[-1000000, float(minAccThresh), 1], [float(minAccThresh), 9999999999, 0]]) outLUCIstream = Reclassify(streamAccHaFile, "VALUE", reclassifyRanges) outLUCIstream.save(streamInvRas) del outLUCIstream log.info("Stream raster for input to LUCI created") # Create stream file for display reclassifyRanges = RemapRange( [[0, float(minAccThresh), "NODATA"], [float(minAccThresh), float(majAccThresh), 1], [float(majAccThresh), 99999999999999, 2]]) streamsRaster = Reclassify(streamAccHaFile, "Value", reclassifyRanges, "NODATA") streamOrderRaster = StreamOrder(streamsRaster, hydFDR, "STRAHLER") streamsRaster.save(streamsRasterFile) # Create two streams feature classes - one for analysis and one for display arcpy.sa.StreamToFeature(streamOrderRaster, hydFDR, streams, 'NO_SIMPLIFY') arcpy.sa.StreamToFeature(streamOrderRaster, hydFDR, streamDisplay, 'SIMPLIFY') # Rename grid_code column to 'Strahler' for streamFC in [streams, streamDisplay]: arcpy.AddField_management(streamFC, "Strahler", "LONG") arcpy.CalculateField_management( streamFC, "Strahler", "!GRID_CODE!", "PYTHON_9.3") arcpy.DeleteField_management(streamFC, "GRID_CODE") del streamsRaster del streamOrderRaster log.info("Stream files created") else: warning = 'No streams initiated' log.warning(warning) common.logWarnings(outputFolder, warning) # Create LUCIStream file from multiplier raster (i.e. all cells have value of 1 = no stream) arcpy.CopyRaster_management(multRaster, streamInvRas) progress.logProgress(codeBlock, outputFolder) codeBlock = 'Clip data, build pyramids and generate statistics' if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun): try: # Generate pyramids and stats arcpy.BuildPyramidsandStatistics_management( outputFolder, "", "", "", "") log.info( "Pyramids and Statistics calculated for all LUCI topographical information rasters" ) except Exception: log.info("Warning - could not generate all raster statistics") progress.logProgress(codeBlock, outputFolder) # Reset snap raster arcpy.env.snapRaster = None except Exception: log.error("Error in preprocessing operations") raise
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 calculate_topographic_properties(**kwargs): """ Description: calculates topographic properties from an elevation raster Inputs: 'z_unit' -- a string value of either 'Meter' or 'Foot' representing the vertical unit of the elevation raster 'input_array' -- an array containing the grid raster (must be first) and the elevation raster 'output_array' -- an array containing the output rasters for aspect, compound topographic index, heat load index, integrated moisture index, roughness, site exposure, slope, surface area ratio, and surface relief ratio (in that order) Returned Value: Returns a raster dataset on disk for each topographic property Preconditions: requires an input DEM that can be created through other scripts in this repository """ # Import packages import arcpy from arcpy.sa import Con from arcpy.sa import IsNull from arcpy.sa import ExtractByMask from arcpy.sa import Raster from arcpy.sa import Int from arcpy.sa import FlowDirection from arcpy.sa import FlowAccumulation from arcpy.sa import Slope from arcpy.sa import Aspect from package_Geomorphometry import compound_topographic from package_Geomorphometry import getZFactor from package_Geomorphometry import linear_aspect from package_Geomorphometry import mean_slope from package_Geomorphometry import roughness from package_Geomorphometry import site_exposure from package_Geomorphometry import surface_area from package_Geomorphometry import surface_relief from package_Geomorphometry import topographic_position from package_Geomorphometry import topographic_radiation import datetime import os import time # Parse key word argument inputs z_unit = kwargs['z_unit'] grid_raster = kwargs['input_array'][0] elevation_input = kwargs['input_array'][1] elevation_output = kwargs['output_array'][0] aspect_output = kwargs['output_array'][1] cti_output = kwargs['output_array'][2] roughness_output = kwargs['output_array'][3] exposure_output = kwargs['output_array'][4] slope_output = kwargs['output_array'][5] area_output = kwargs['output_array'][6] relief_output = kwargs['output_array'][7] position_output = kwargs['output_array'][8] radiation_output = kwargs['output_array'][9] # Set overwrite option arcpy.env.overwriteOutput = True # Use two thirds of cores on processes that can be split. arcpy.env.parallelProcessingFactor = "75%" # Set snap raster and extent arcpy.env.snapRaster = grid_raster arcpy.env.extent = Raster(grid_raster).extent # Define folder structure grid_title = os.path.splitext(os.path.split(grid_raster)[1])[0] raster_folder = os.path.split(elevation_output)[0] intermediate_folder = os.path.join(raster_folder, 'intermediate') # Create raster folder if it does not already exist if os.path.exists(raster_folder) == 0: os.mkdir(raster_folder) # Create intermediate folder if it does not already exist if os.path.exists(intermediate_folder) == 0: os.mkdir(intermediate_folder) # Define intermediate datasets flow_direction_raster = os.path.join(intermediate_folder, 'flow_direction.tif') flow_accumulation_raster = os.path.join(intermediate_folder, 'flow_accumulation.tif') raw_slope_raster = os.path.join(intermediate_folder, 'raw_slope.tif') raw_aspect_raster = os.path.join(intermediate_folder, 'raw_aspect.tif') # Get the z factor appropriate to the xy and z units zFactor = getZFactor(elevation_input, z_unit) #### CALCULATE INTERMEDIATE DATASETS # Calculate flow direction if it does not already exist if os.path.exists(flow_direction_raster) == 0: # Calculate flow direction print(f'\tCalculating flow direction for {grid_title}...') iteration_start = time.time() flow_direction = FlowDirection(elevation_input, 'NORMAL', '', 'D8') flow_direction.save(flow_direction_raster) # End timing iteration_end = time.time() iteration_elapsed = int(iteration_end - iteration_start) iteration_success_time = datetime.datetime.now() # Report success print( f'\tCompleted at {iteration_success_time.strftime("%Y-%m-%d %H:%M")} (Elapsed time: {datetime.timedelta(seconds=iteration_elapsed)})' ) print('\t----------') else: print(f'\tFlow direction already exists for {grid_title}.') print('\t----------') # Calculate flow accumulation if it does not already exist if os.path.exists(flow_accumulation_raster) == 0: # Calculate flow accumulation print(f'\tCalculating flow accumulation for {grid_title}...') iteration_start = time.time() flow_accumulation = FlowAccumulation(flow_direction_raster, '', 'FLOAT', 'D8') flow_accumulation.save(flow_accumulation_raster) # End timing iteration_end = time.time() iteration_elapsed = int(iteration_end - iteration_start) iteration_success_time = datetime.datetime.now() # Report success print( f'\tCompleted at {iteration_success_time.strftime("%Y-%m-%d %H:%M")} (Elapsed time: {datetime.timedelta(seconds=iteration_elapsed)})' ) print('\t----------') else: print(f'\tFlow accumulation already exists for {grid_title}.') print('\t----------') # Calculate raw slope in degrees if it does not already exist if os.path.exists(raw_slope_raster) == 0: # Calculate slope print(f'\tCalculating raw slope for {grid_title}...') iteration_start = time.time() raw_slope = Slope(elevation_input, "DEGREE", zFactor) raw_slope.save(raw_slope_raster) # End timing iteration_end = time.time() iteration_elapsed = int(iteration_end - iteration_start) iteration_success_time = datetime.datetime.now() # Report success print( f'\tCompleted at {iteration_success_time.strftime("%Y-%m-%d %H:%M")} (Elapsed time: {datetime.timedelta(seconds=iteration_elapsed)})' ) print('\t----------') else: print(f'\tRaw slope already exists for {grid_title}.') print('\t----------') # Calculate raw aspect if it does not already exist if os.path.exists(raw_aspect_raster) == 0: # Calculate aspect print(f'\tCalculating raw aspect for {grid_title}...') iteration_start = time.time() raw_aspect = Aspect(elevation_input, 'PLANAR', z_unit) raw_aspect.save(raw_aspect_raster) # End timing iteration_end = time.time() iteration_elapsed = int(iteration_end - iteration_start) iteration_success_time = datetime.datetime.now() # Report success print( f'\tCompleted at {iteration_success_time.strftime("%Y-%m-%d %H:%M")} (Elapsed time: {datetime.timedelta(seconds=iteration_elapsed)})' ) print('\t----------') else: print(f'\tRaw aspect already exists for {grid_title}.') print('\t----------') #### CALCULATE INTEGER ELEVATION # Calculate integer elevation if it does not already exist if arcpy.Exists(elevation_output) == 0: print(f'\tCalculating integer elevation for {grid_title}...') iteration_start = time.time() # Round to integer print(f'\t\tConverting values to integers...') integer_elevation = Int(Raster(elevation_input) + 0.5) # Copy extracted raster to output print(f'\t\tCreating output raster...') arcpy.management.CopyRaster(integer_elevation, elevation_output, '', '', '-32768', 'NONE', 'NONE', '16_BIT_SIGNED', 'NONE', 'NONE', 'TIFF', 'NONE') # End timing iteration_end = time.time() iteration_elapsed = int(iteration_end - iteration_start) iteration_success_time = datetime.datetime.now() # Report success print( f'\tCompleted at {iteration_success_time.strftime("%Y-%m-%d %H:%M")} (Elapsed time: {datetime.timedelta(seconds=iteration_elapsed)})' ) print('\t----------') else: print(f'\tInteger elevation already exists for {grid_title}.') print('\t----------') #### CALCULATE LINEAR ASPECT # Calculate linear aspect if it does not already exist if arcpy.Exists(aspect_output) == 0: print(f'\tCalculating linear aspect for {grid_title}...') iteration_start = time.time() # Create an initial linear aspect calculation using the linear aspect function aspect_intermediate = os.path.splitext( aspect_output)[0] + '_intermediate.tif' linear_aspect(raw_aspect_raster, aspect_intermediate) # Round to integer print(f'\t\tConverting values to integers...') integer_aspect = Int(Raster(aspect_intermediate) + 0.5) # Fill missing data (no aspect) with values of -1 print(f'\t\tFilling values of no aspect...') conditional_aspect = Con(IsNull(integer_aspect), -1, integer_aspect) # Extract filled raster to grid mask print(f'\t\tExtracting filled raster to grid...') extract_aspect = ExtractByMask(conditional_aspect, grid_raster) # Copy extracted raster to output print(f'\t\tCreating output raster...') arcpy.management.CopyRaster(extract_aspect, aspect_output, '', '', '-32768', 'NONE', 'NONE', '16_BIT_SIGNED', 'NONE', 'NONE', 'TIFF', 'NONE') # End timing iteration_end = time.time() iteration_elapsed = int(iteration_end - iteration_start) iteration_success_time = datetime.datetime.now() # Delete intermediate dataset if possible try: arcpy.management.Delete(aspect_intermediate) except: print('\t\tCould not delete intermediate dataset...') # Report success print( f'\tCompleted at {iteration_success_time.strftime("%Y-%m-%d %H:%M")} (Elapsed time: {datetime.timedelta(seconds=iteration_elapsed)})' ) print('\t----------') else: print(f'\tLinear aspect already exists for {grid_title}.') print('\t----------') #### CALCULATE COMPOUND TOPOGRAPHIC INDEX # Calculate compound topographic index if it does not already exist if arcpy.Exists(cti_output) == 0: print(f'\tCalculating compound topographic index for {grid_title}...') iteration_start = time.time() # Create an intermediate compound topographic index calculation cti_intermediate = os.path.splitext( cti_output)[0] + '_intermediate.tif' compound_topographic(elevation_input, flow_accumulation_raster, raw_slope_raster, cti_intermediate) # Convert to integer values print(f'\t\tConverting values to integers...') integer_compound = Int((Raster(cti_intermediate) * 100) + 0.5) # Copy integer raster to output print(f'\t\tCreating output raster...') arcpy.management.CopyRaster(integer_compound, cti_output, '', '', '-32768', 'NONE', 'NONE', '16_BIT_SIGNED', 'NONE', 'NONE', 'TIFF', 'NONE') # End timing iteration_end = time.time() iteration_elapsed = int(iteration_end - iteration_start) iteration_success_time = datetime.datetime.now() # Delete intermediate dataset if possible try: arcpy.management.Delete(cti_intermediate) except: print('\t\tCould not delete intermediate dataset...') # Report success print( f'\tCompleted at {iteration_success_time.strftime("%Y-%m-%d %H:%M")} (Elapsed time: {datetime.timedelta(seconds=iteration_elapsed)})' ) print('\t----------') else: print(f'\tCompound topographic index already exists for {grid_title}.') print('\t----------') #### CALCULATE ROUGHNESS # Calculate roughness if it does not already exist if arcpy.Exists(roughness_output) == 0: print(f'\tCalculating roughness for {grid_title}...') iteration_start = time.time() # Create an intermediate compound topographic index calculation roughness_intermediate = os.path.splitext( roughness_output)[0] + '_intermediate.tif' roughness(elevation_input, roughness_intermediate) # Convert to integer values print(f'\t\tConverting values to integers...') integer_roughness = Int(Raster(roughness_intermediate) + 0.5) # Fill missing data (no aspect) with values of 0 print(f'\t\tFilling values of roughness...') conditional_roughness = Con(IsNull(integer_roughness), 0, integer_roughness) # Extract filled raster to grid mask print(f'\t\tExtracting filled raster to grid...') extract_roughness = ExtractByMask(conditional_roughness, grid_raster) # Copy extracted raster to output print(f'\t\tCreating output raster...') arcpy.management.CopyRaster(extract_roughness, roughness_output, '', '', '-32768', 'NONE', 'NONE', '16_BIT_SIGNED', 'NONE', 'NONE', 'TIFF', 'NONE') # End timing iteration_end = time.time() iteration_elapsed = int(iteration_end - iteration_start) iteration_success_time = datetime.datetime.now() # Delete intermediate dataset if possible try: arcpy.management.Delete(roughness_intermediate) except: print('\t\tCould not delete intermediate dataset...') # Report success print( f'\tCompleted at {iteration_success_time.strftime("%Y-%m-%d %H:%M")} (Elapsed time: {datetime.timedelta(seconds=iteration_elapsed)})' ) print('\t----------') else: print(f'\tRoughness already exists for {grid_title}.') print('\t----------') #### CALCULATE SITE EXPOSURE # Calculate site exposure if it does not already exist if arcpy.Exists(exposure_output) == 0: print(f'\tCalculating site exposure for {grid_title}...') iteration_start = time.time() # Create an intermediate compound topographic index calculation exposure_intermediate = os.path.splitext( exposure_output)[0] + '_intermediate.tif' site_exposure(raw_aspect_raster, raw_slope_raster, exposure_intermediate) # Convert to integer values print(f'\t\tConverting values to integers...') integer_exposure = Int((Raster(exposure_intermediate) * 100) + 0.5) # Copy extracted raster to output print(f'\t\tCreating output raster...') arcpy.management.CopyRaster(integer_exposure, exposure_output, '', '', '-32768', 'NONE', 'NONE', '16_BIT_SIGNED', 'NONE', 'NONE', 'TIFF', 'NONE') # End timing iteration_end = time.time() iteration_elapsed = int(iteration_end - iteration_start) iteration_success_time = datetime.datetime.now() # Delete intermediate dataset if possible try: arcpy.management.Delete(exposure_intermediate) except: print('\t\tCould not delete intermediate dataset...') # Report success print( f'\tCompleted at {iteration_success_time.strftime("%Y-%m-%d %H:%M")} (Elapsed time: {datetime.timedelta(seconds=iteration_elapsed)})' ) print('\t----------') else: print(f'\tSite exposure already exists for {grid_title}.') print('\t----------') #### CALCULATE MEAN SLOPE # Calculate mean slope if it does not already exist if arcpy.Exists(slope_output) == 0: print(f'\tCalculating mean slope for {grid_title}...') iteration_start = time.time() # Create an intermediate mean slope calculation slope_intermediate = os.path.splitext( slope_output)[0] + '_intermediate.tif' mean_slope(raw_slope_raster, slope_intermediate) # Convert to integer values print(f'\t\tConverting values to integers...') integer_slope = Int(Raster(slope_intermediate) + 0.5) # Copy extracted raster to output print(f'\t\tCreating output raster...') arcpy.management.CopyRaster(integer_slope, slope_output, '', '', '-128', 'NONE', 'NONE', '8_BIT_SIGNED', 'NONE', 'NONE', 'TIFF', 'NONE') # End timing iteration_end = time.time() iteration_elapsed = int(iteration_end - iteration_start) iteration_success_time = datetime.datetime.now() # Delete intermediate dataset if possible try: arcpy.management.Delete(slope_intermediate) except: print('\t\tCould not delete intermediate dataset...') # Report success print( f'\tCompleted at {iteration_success_time.strftime("%Y-%m-%d %H:%M")} (Elapsed time: {datetime.timedelta(seconds=iteration_elapsed)})' ) print('\t----------') else: print(f'\tMean slope already exists for {grid_title}.') print('\t----------') #### CALCULATE SURFACE AREA RATIO # Calculate surface area ratio if it does not already exist if os.path.exists(area_output) == 0: print(f'\tCalculating surface area ratio for {grid_title}...') iteration_start = time.time() # Create an intermediate surface area ratio calculation area_intermediate = os.path.splitext( area_output)[0] + '_intermediate.tif' surface_area(raw_slope_raster, area_intermediate) # Convert to integer values print(f'\t\tConverting values to integers...') integer_area = Int((Raster(area_intermediate) * 10) + 0.5) # Copy extracted raster to output print(f'\t\tCreating output raster...') arcpy.management.CopyRaster(integer_area, area_output, '', '', '-32768', 'NONE', 'NONE', '16_BIT_SIGNED', 'NONE', 'NONE', 'TIFF', 'NONE') # End timing iteration_end = time.time() iteration_elapsed = int(iteration_end - iteration_start) iteration_success_time = datetime.datetime.now() # Delete intermediate dataset if possible try: arcpy.management.Delete(area_intermediate) except: print('\t\tCould not delete intermediate dataset...') # Report success print( f'\tCompleted at {iteration_success_time.strftime("%Y-%m-%d %H:%M")} (Elapsed time: {datetime.timedelta(seconds=iteration_elapsed)})' ) print('\t----------') else: print(f'\tSurface area ratio already exists for {grid_title}.') print('\t----------') #### CALCULATE SURFACE RELIEF RATIO # Calculate surface relief ratio if it does not already exist if arcpy.Exists(relief_output) == 0: print(f'\tCalculating surface relief ratio for {grid_title}...') iteration_start = time.time() # Create an intermediate surface relief ratio calculation relief_intermediate = os.path.splitext( relief_output)[0] + '_intermediate.tif' surface_relief(elevation_input, relief_intermediate) # Convert to integer values print(f'\t\tConverting values to integers...') integer_relief = Int((Raster(relief_intermediate) * 1000) + 0.5) # Copy extracted raster to output print(f'\t\tCreating output raster...') arcpy.management.CopyRaster(integer_relief, relief_output, '', '', '-32768', 'NONE', 'NONE', '16_BIT_SIGNED', 'NONE', 'NONE', 'TIFF', 'NONE') # End timing iteration_end = time.time() iteration_elapsed = int(iteration_end - iteration_start) iteration_success_time = datetime.datetime.now() # Delete intermediate dataset if possible try: arcpy.management.Delete(relief_intermediate) except: print('\t\tCould not delete intermediate dataset...') # Report success print( f'\tCompleted at {iteration_success_time.strftime("%Y-%m-%d %H:%M")} (Elapsed time: {datetime.timedelta(seconds=iteration_elapsed)})' ) print('\t----------') else: print(f'\tSurface relief ratio already exists for {grid_title}.') print('\t----------') #### CALCULATE TOPOGRAPHIC POSITION # Calculate topographic position if it does not already exist if arcpy.Exists(position_output) == 0: print(f'\tCalculating topographic position for {grid_title}...') iteration_start = time.time() # Create an intermediate topographic position calculation position_intermediate = os.path.splitext( position_output)[0] + '_intermediate.tif' topographic_position(elevation_input, position_intermediate) # Convert to integer values print(f'\t\tConverting values to integers...') integer_position = Int((Raster(position_intermediate) * 100) + 0.5) # Copy extracted raster to output print(f'\t\tCreating output raster...') arcpy.management.CopyRaster(integer_position, position_output, '', '', '-32768', 'NONE', 'NONE', '16_BIT_SIGNED', 'NONE', 'NONE', 'TIFF', 'NONE') # End timing iteration_end = time.time() iteration_elapsed = int(iteration_end - iteration_start) iteration_success_time = datetime.datetime.now() # Delete intermediate dataset if possible try: arcpy.management.Delete(position_intermediate) except: print('\t\tCould not delete intermediate dataset...') # Report success print( f'\tCompleted at {iteration_success_time.strftime("%Y-%m-%d %H:%M")} (Elapsed time: {datetime.timedelta(seconds=iteration_elapsed)})' ) print('\t----------') else: print(f'\tTopographic position already exists for {grid_title}.') print('\t----------') #### CALCULATE TOPOGRAPHIC RADIATION # Calculate topographic radiation if it does not already exist if arcpy.Exists(radiation_output) == 0: print(f'\tCalculating topographic radiation for {grid_title}...') iteration_start = time.time() # Create an intermediate topographic position calculation radiation_intermediate = os.path.splitext( radiation_output)[0] + '_intermediate.tif' radiation_integer = os.path.splitext( radiation_output)[0] + '_integer.tif' topographic_radiation(elevation_input, radiation_intermediate) # Convert to integer values print(f'\t\tConverting values to integers...') integer_radiation = Int((Raster(radiation_intermediate) * 1000) + 0.5) arcpy.management.CopyRaster(integer_radiation, radiation_integer, '', '', '-32768', 'NONE', 'NONE', '16_BIT_SIGNED', 'NONE', 'NONE', 'TIFF', 'NONE') # Extract filled raster to grid mask print(f'\t\tExtracting integer raster to grid...') extract_radiation = ExtractByMask(radiation_integer, grid_raster) # Copy extracted raster to output print(f'\t\tCreating output raster...') arcpy.management.CopyRaster(extract_radiation, radiation_output, '', '', '-32768', 'NONE', 'NONE', '16_BIT_SIGNED', 'NONE', 'NONE', 'TIFF', 'NONE') # End timing iteration_end = time.time() iteration_elapsed = int(iteration_end - iteration_start) iteration_success_time = datetime.datetime.now() # Delete intermediate dataset if possible try: arcpy.management.Delete(radiation_intermediate) arcpy.management.Delete(radiation_integer) except: print('\t\tCould not delete intermediate dataset...') # Report success print( f'\tCompleted at {iteration_success_time.strftime("%Y-%m-%d %H:%M")} (Elapsed time: {datetime.timedelta(seconds=iteration_elapsed)})' ) print('\t----------') else: print(f'\tTopographic radiation already exists for {grid_title}.') print('\t----------') outprocess = f'Finished topographic properties for {grid_title}.' return outprocess