def get_hypsometry (feature, dem, workspace, raster_scaling = 1000, max_bin = 8850, min_bin = 0, bin_size = 50): """Calculate hypsometry information from the given digital elevation model (DEM) and return bin statistics. If this function fails at runtime an error is returned for recording in the log file.""" hypsometry = [] try: reclassify_range = '' # re-map string elevation_list = [] # List containing the area and elevation values # Generate re-map string for the reclassify function. This done by first # calculating the number of bins and then finding the low and high values # for each bin and then giving it a label. total_bins = round(math.ceil(float(max_bin - min_bin) / float(bin_size)), 0) for bin_num in range (0, int(total_bins)): # For each bin... low_value = bin_num * bin_size # Low value in range and re-map value high = float((bin_num + 1) * bin_size) # High value in range reclassify_range += str(float(low_value)) + " " + str(high) + " " + str(low_value) + ";" hypsometry.append(float(low_value)) # Append the bin value to the hypsometry list # Reclassify the DEM based on bins reclassify = workspace + '\\' + 'Reclassify_Raster_' + str(feature.GLIMSID) + '.img' reclass_raster = spatial.Reclassify (dem, "Value", reclassify_range, "NODATA") reclass_raster.save(reclassify) # Create a clipped feature from the input raster. bin_features = raster_to_polygon(feature, reclassify, workspace, raster_scaling) # Iterate over the feature table and generate a list of bin values and area of each rows = ARCPY.SearchCursor(bin_features) for row in rows: elevation_list.append([float(row.GRIDCODE/raster_scaling), float(row.F_AREA)]) del row, rows item_found = False # Switch to identify if an element exists or not current_bin = 0.0 # Bin value to print for index, hypso_bin in enumerate (hypsometry): # For each hypsometry bin for item in elevation_list: # Loop through the elevation list if item[0] == hypso_bin: # If the value in elev. List is found... current_bin += item[1] # ... add it to the hypsometry list item_found = True if item_found == False: # If an element is NOT found in elevation list... hypsometry[index] = str(0.0) # set elevation bin to 0.0 else: # If an element is found # Set elevation bin to sum of values and remove decimals by rounding hypsometry[index] = str(round(current_bin, 0)) item_found = False # Reset the switch current_bin = 0.0 # Reset bin value to print ARCPY.Delete_management(reclassify) # Remove the reclassified raster from workspace return hypsometry, False, bin_features except: return hypsometry, True, False
def bin_by_dem(feature, dem, scratch, name=None, bin_size=50): """Calculate bins from the given digital elevation model (DEM) and return bin statistics.""" # Build Export Name. This option is largely included in case there is unexpected # naming conflicts with other functions if name == '' or name == None: name = os.path.join(scratch, 'Binned.shp') else: name = os.path.join(scratch, name) min_bin = 0 # Force default min_bin to sea level. DO NOT CHANGE. max_bin = 8850 reclassify_range = '' # re-map string # Generate re-map string for the reclassify function. This done by first # calculating the number of bins and then finding the low and high values # for each bin and then giving it a label. total_bins = round(math.ceil(float(max_bin - min_bin) / float(bin_size)), 0) for bin_num in range(0, int(total_bins)): # For each bin... low_value = bin_num * bin_size # Low value in range and re-map value high_value = (bin_num + 1) * bin_size # High value in range reclassify_range += str(float(low_value)) + " " + str( float(high_value)) + " " + str(low_value) + ";" # Reclassify the DEM based on bins filled = spatial.Fill(dem) # Fill DEM reclass_raster = spatial.Reclassify(filled, "Value", reclassify_range, "NODATA") # Create a clipped feature from the input raster. poly_raster = raster_to_polygon(feature, reclass_raster, scratch, '', 1) # Clip and clean to the original input feature arcpy.Clip_analysis(poly_raster, feature, name) # Format output table. to_delete = get_fields(name) fields = [('BINS', 'INTEGER', "'!grid_code!'"), ('STEP_SIZE', 'INTEGER', bin_size)] for field in fields: arcpy.AddField_management(name, field[0], field[1]) arcpy.CalculateField_management(name, field[0], field[2], 'PYTHON') for item in to_delete: arcpy.DeleteField_management(name, item) arcpy.Delete_management(filled) arcpy.Delete_management(poly_raster) return name
if debug == True: arcpy.AddMessage( str( time.strftime("copyraster: %m/%d/%Y %H:%M:%S", time.localtime()))) scratchSlope = os.path.join("in_memory", "scratchSlope") arcpy.CopyRaster_management("SlopeLayer", scratchSlope) deleteme.append(scratchSlope) reclassSlope = os.path.join(scratch, "reclassSlope") if debug == True: arcpy.AddMessage( str( time.strftime("Reclassify: %m/%d/%Y %H:%M:%S", time.localtime()))) arcpy.AddMessage("Reclassifying slope...") reclass = sa.Reclassify(scratchSlope, "VALUE", remap, missing_values) reclass.save(reclassSlope) deleteme.append(reclassSlope) #clean edges boundaryClean = os.path.join(scratch, "boundaryClean") if debug == True: arcpy.AddMessage( str( time.strftime("BoundaryClean: %m/%d/%Y %H:%M:%S", time.localtime()))) clean = sa.BoundaryClean(reclassSlope, "NO_SORT", "TWO_WAY") clean.save(boundaryClean) deleteme.append(boundaryClean) # Convert reclassified slope ranges to polygon features slopePoly = os.path.join(scratch, "slopePoly")
tciRaster1 = sa.Ln(sa.Plus(flacRaster, 30.0) / sa.Tan(slopeRad)) # Where slope is zero, set TCI to its max value tciRaster = sa.Con(slopeRad, tciRaster1.maximum, tciRaster1, "Value = 0") # Create class breaks according to the method selected if parseMethod in ("EQUAL_INTERVAL", "EQUAL_AREA"): msg("Using equal interval breaks") #Slice values msg("...decomposing values into equal quantiles") elevSlice = sa.Slice(elevRaster, 5, parseMethod, 1) * 100 solSlice = sa.Slice(solRaster, 5, parseMethod, 1) tciSlice = sa.Slice(tciRaster, 5, parseMethod, 1) # Remap the extremes of the solar and tci rasters msg("...recoding group values") remap = sa.RemapValue([[1, 1], [2, 2], [3, 2], [4, 2], [5, 3]]) solRemap = sa.Reclassify(solSlice, "VALUE", remap) * 10 tciRemap = sa.Reclassify(tciSlice, "VALUE", remap) # Combine into zip codes msg("...combining values into zip codes") msg("Computing zipcodes") zipCodes = elevSlice + solRemap + tciRemap zipCodes.save(zipCodeRaster) msg("Output saved to %s" % zipCodeRaster) elif parseMethod == ("EO BREAKS"): msg("Using natural breaks informed by element occurrences") # Create a feature class of Plant EOs with good precision whereClause = "\"UNCRT_DIST\" <= 1000 AND \"NAME_CATGY\" IN ( 'Vascular Plant', 'Nonvascular Plant', 'Natural Community')" plantEOs = arcpy.MakeFeatureLayer_management(EOs, "plantEOs", whereClause) # Find class breaks using EO locations msg("Extracting data at element occurrence locations")
def krigingFromPointCSV(inTable, valueField, xField, yField, inClipFc, workspace = "assignment3.gdb"): # Import necessary modules import arcpy import arcpy.sa as sa import os import sys import traceback # Allow overwriting arcpy.env.overwriteOutput = True # Set workspace environment arcpy.env.workspace = workspace # Define custom exceptions class WorkspaceExistsError(Exception): pass class inTableExistsError(Exception): pass class valueFieldExistsError(Exception): pass class xFieldExistsError(Exception): pass class yFieldExistsError(Exception): pass class inClipFcExistsError(Exception): pass class inClipFcShapeError(Exception): pass class LicenseError(Exception): pass # Check that all specified files exist and parameters are valid try: # Test if workspace exists if arcpy.Exists(workspace): print("Specified workspace has been found.") else: raise WorkspaceExistsError # Test if inTable exists if arcpy.Exists(inTable): print("Specified table has been found.") else: raise inTableExistsError # Test if valueField, xField, and yField exist in inTable fields = arcpy.ListFields(inTable) fieldstest = [] for f in fields: fieldstest.append(f.name) if valueField in fieldstest: print("Specified value field has been found in the table.") else: raise valueFieldExistsError if xField in fieldstest: print("Specified x field has been found in the table.") else: raise xFieldExistsError if yField in fieldstest: print("Specified y field has been found in the table.") else: raise yFieldExistsError # Test if inClipFc exists if arcpy.Exists(inClipFc): print("Specified feature class has been found.") else: raise inClipFcExistsError # Test if polygon feature class shapeType parameter is valid descclip = arcpy.Describe(inClipFc) if descclip.shapeType != "Polygon": raise inClipFcShapeError else: print("Specified feature class has the correct shape type for this script (polygon).") # Check for Spatial Analyst license if arcpy.CheckExtension("Spatial") == "Available": arcpy.CheckOutExtension("Spatial") print("Spatial Analyst license recognized.") else: raise LicenseError except WorkspaceExistsError: print("WorkspaceExistsError: The specified workspace could not be found!") except inTableExistsError: print("inTableExistsError: The specified table could not be found!") except valueFieldExistsError: print("valueFieldExistsError: The specified value field could not be found!") except xFieldExistsError: print("xFieldExistsError: The specified x field could not be found!") except yFieldExistsError: print("yFieldExistsError: The specified y field could not be found!") except inClipFcExistsError: print("inClipFcExistsError: The specified feature class could not be found!") except inClipFcShapeError: print("inClipFcShapeError: The specified feature class must be a polygon shape type!") except LicenseError: print("LicenseError: Spatial Analyst license is unavailable!") # If no exceptions are raised, attempt to carry out the procedure else: try: # Generate an input feature layer using inTable points = inTable + "_points" arcpy.management.XYTableToPoint(inTable, points, xField, yField) print("Point layer created.") # Create spatial reference object for inClipFc spatial_ref = descclip.spatialReference # Project the points feature layer to the system used by inClipFc prjpoints = inTable + "_prjpoints" arcpy.management.Project(points, prjpoints, spatial_ref) print("Point layer projected to match input polygon feature class.") # Create a cellSize variable based on the extent descpoints = arcpy.Describe(prjpoints) cellSize = 0 width = descpoints.extent.width height = descpoints.extent.height if width < height: cellSize = width / 1000 else: cellSize = height / 1000 # Naming convention for kriging output kname = valueField + "_K" # Interpolate raster surface from points using kriging and save the output outKriging = sa.Kriging(prjpoints, valueField, '#', cellSize) outKriging.save(kname) print("Points interpolated to create raster.") # Define bounding box rectangle rectangle = str(descclip.extent.XMin) + " " + str(descclip.extent.YMin) + " " + str(descclip.extent.XMax) + " " + str(descclip.extent.YMax) # Naming convention for clipped kriging output cname = kname + "_C" # Clip the kriging output using the defined feature class arcpy.Clip_management(kname, rectangle, cname, inClipFc, "#", "ClippingGeometry", "MAINTAIN_EXTENT") print("Raster layer clipped.") # Naming convention for integerized raster iname = cname + "_I" # Truncate raster cell values to integers and save the output outInt = sa.Int(cname) outInt.save(iname) print("Clipped raster layer values truncated to integers.") # Get minimum and maximum cell values min_F2018 = arcpy.management.GetRasterProperties(outInt, "MINIMUM") max_F2018 = arcpy.management.GetRasterProperties(outInt, "MAXIMUM") min_2018 = int(min_F2018.getOutput(0)) max_2018 = int(max_F2018.getOutput(0)) # Define the number of classes to use numofclasses = 5 # Use number of classes and min and max values to calculate equal intervals eq_interval = (max_2018 - min_2018) / numofclasses # Create classification scheme remapRangeList = [] mybreak = min_2018 for i in range(0, numofclasses): newClassCode = i + 1 lowerBound = int(mybreak) upperBound = int(mybreak + eq_interval) remap = [lowerBound, upperBound, newClassCode] remapRangeList.append(remap) mybreak += eq_interval # Reclassify the raster rname = iname + "_R" outReclassRR = sa.Reclassify(iname, "Value", sa.RemapRange(remapRangeList), "NODATA") outReclassRR.save(rname) print("Raster values reclassified.") # Convert the raster into a polygon feature class arcpy.RasterToPolygon_conversion(rname, valueField + "_ismc") print("Raster converted to vector (polygon feature class).") # Delete unnecessary intermediate stages del1 = os.path.join(workspace, points) del2 = os.path.join(workspace, prjpoints) del3 = os.path.join(workspace, kname) del4 = os.path.join(workspace, cname) del5 = os.path.join(workspace, iname) del6 = os.path.join(workspace, rname) arcpy.management.Delete([del1,del2,del3,del4,del5,del6]) print("Unnecessary files deleted.") # Catch-all exception handling except arcpy.ExecuteError: # Get the tool error messages msgs = arcpy.GetMessages(2) # Return tool error messages for use with a script tool arcpy.AddError(msgs) # Print tool error messages for use in Python print("Tool Error:", msgs) except: # Get the traceback object tb = sys.exc_info()[2] tbinfo = traceback.format_tb(tb)[0] # Put error information into a message string pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1]) msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n" # Return python error messages for use in script tool or Python window arcpy.AddError(pymsg) arcpy.AddError(msgs) # Print Python error messages for use in Python / Python window print(pymsg) print(msgs) else: print("All script operations now complete!")