Пример #1
0
def main(bathy=None, out_sin_raster=None, out_cos_raster=None):
    """
    Calculate the statistical aspect of a raster, which
    computes the sin(aspect) and cos(aspect). By using these two
    variables, aspect can be accounted for as a continuous circular
    variable. Because aspect is circular (0 and 359.9 are immediately
    adjacent), this trigonometric transformation preserves distances
    between elements and is the simplest transformation mechanism.
    """

    try:
        arcpy.env.rasterStatistics = "STATISTICS"
        # Calculate the aspect of the bathymetric raster. "Aspect is expressed
        # in positive degrees from 0 to 359.9, measured clockwise from north."
        utils.msg("Calculating aspect...")
        aspect = Aspect(bathy)

        # Both the sin and cos functions here expect radians, not degrees.
        # convert our Aspect raster into radians, check that the values
        # are in range.
        aspect_rad = aspect * (math.pi / 180)

        aspect_sin = Sin(aspect_rad)
        aspect_cos = Cos(aspect_rad)

        out_sin_raster = utils.validate_path(out_sin_raster)
        out_cos_raster = utils.validate_path(out_cos_raster)
        aspect_sin.save(out_sin_raster)
        aspect_cos.save(out_cos_raster)
    except Exception as e:
        utils.msg(e, mtype='error')
Пример #2
0
def topographic_radiation(raw_aspect, radiation_output):
    """
    Description: calculates 32-bit float topographic radiation
    Inputs: 'raw_aspect' -- an input raw aspect raster
            'radiation_output' -- an output topographic radiation raster
    Returned Value: Returns a raster dataset on disk
    Preconditions: requires an input raw aspect raster
    """

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

    # Set overwrite option
    arcpy.env.overwriteOutput = True

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

    # Convert negative aspect values
    print('\t\tConverting negative aspect values...')
    out_raster = Con(Raster(raw_aspect) < 0, 0.5, radiation_index)
    out_raster.save(radiation_output)
Пример #3
0
def site_exposure(raw_aspect, raw_slope, exposure_output):
    """
    Description: calculates 32-bit float site exposure
    Inputs: 'raw_aspect' -- an input raw aspect raster
            'raw_slope' -- an input raster digital elevation model
            'exposure_output' -- an output exposure raster
    Returned Value: Returns a raster dataset on disk
    Preconditions: requires an input aspect and slope raster
    """

    # Import packages
    import arcpy
    from arcpy.sa import Cos
    from arcpy.sa import Divide
    from arcpy.sa import Minus
    from arcpy.sa import Raster
    from arcpy.sa import Times

    # Set overwrite option
    arcpy.env.overwriteOutput = True

    # Calculate cosine of modified aspect
    print('\t\tCalculating cosine of modified aspect...')
    cosine = Cos(Divide(Times(3.142, Minus(Raster(raw_aspect), 180)), 180))

    # Calculate site exposure index and save output
    print('\t\tCalculating site exposure index...')
    out_raster = Times(Raster(raw_slope), cosine)
    out_raster.save(exposure_output)
Пример #4
0
def main(bathy=None, out_sin_raster=None, out_cos_raster=None):
    """
    Calculate the statistical aspect of a raster, which
    computes the sin(aspect) and cos(aspect). By using these two
    variables, aspect can be accounted for as a continuous circular
    variable. Because aspect is circular (0 and 359.9 are immediately
    adjacent), this trigonometric transformation preserves distances
    between elements and is the simplest transformation mechanism.
    """

    try:
        arcpy.env.compression = "LZW"
        arcpy.env.rasterStatistics = "STATISTICS"
        # Calculate the aspect of the bathymetric raster. "Aspect is expressed
        # in positive degrees from 0 to 359.9, measured clockwise from north."
        utils.msg("Calculating aspect...")
        aspect = Aspect(bathy)

        # Both the sin and cos functions here expect radians, not degrees.
        # convert our Aspect raster into radians, check that the values
        # are in range.
        aspect_rad = aspect * (math.pi / 180)

        aspect_sin = Sin(aspect_rad)
        aspect_cos = Cos(aspect_rad)

        out_sin_raster = utils.validate_path(out_sin_raster)
        out_cos_raster = utils.validate_path(out_cos_raster)
        arcpy.CopyRaster_management(aspect_sin, out_sin_raster)
        arcpy.CopyRaster_management(aspect_cos, out_cos_raster)
    except Exception as e:
        utils.msg(e, mtype='error')
Пример #5
0
def main(bathy=None, out_sin_raster=None, out_cos_raster=None):
    try:
        arcpy.env.rasterStatistics = "STATISTICS"
        # Calculate the aspect of the bathymetric raster. "Aspect is expressed in 
        # positive degrees from 0 to 359.9, measured clockwise from north."
        utils.msg("Calculating aspect...")
        aspect = Aspect(bathy)

        # both the sin and cos functions here expect radians, not degrees.
        # convert our Aspect raster into radians, check that the values are in range.
        aspect_rad = aspect * (math.pi / 180)

        # because this statistic is circular (0 and 359.9 are immediately adjacent),
        # we need to transform this into a form which preserves distances between items.
        # trig is the simplest mechanism.
        aspect_sin = Sin(aspect_rad)
        aspect_cos = Cos(aspect_rad)

        out_sin_raster = utils.validate_path(out_sin_raster)
        out_cos_raster = utils.validate_path(out_cos_raster)
        aspect_sin.save(out_sin_raster)
        aspect_cos.save(out_cos_raster)
    except Exception as e:
        utils.msg(e, mtype='error')
Пример #6
0
def linear_aspect(raw_aspect, aspect_output):
    """
    Description: calculates 32-bit float linear aspect
    Inputs: 'raw_aspect' -- an input raw aspect raster
            'aspect_output' -- an output linear aspect raster
    Returned Value: Returns a raster dataset on disk
    Preconditions: requires an input DEM
    """

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

    # Set overwrite option
    arcpy.env.overwriteOutput = True

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

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

    # Save output raster file
    out_raster.save(aspect_output)
Пример #7
0
def surface_area(raw_slope, area_output):
    """
    Description: calculates 32-bit float surface area ratio
    Inputs: 'raw_slope' -- an input raw slope raster
            'roughness_output' -- an output roughness raster
    Returned Value: Returns a raster dataset on disk
    Preconditions: requires an input elevation raster
    """

    # Import packages
    import arcpy
    from arcpy.sa import Cos
    from arcpy.sa import Float
    from arcpy.sa import Raster
    import math

    # Set overwrite option
    arcpy.env.overwriteOutput = True

    # Getting info on raster
    description = arcpy.Describe(raw_slope)
    cell_size = description.meanCellHeight

    # Set the cell size environment
    arcpy.env.cellSize = cell_size

    # Calculate cell area
    cell_area = cell_size * cell_size

    # Modify raw slope
    print('\t\tModifying raw slope...')
    modifier = math.pi / 180
    modified_slope = Raster(raw_slope) * modifier

    # Calculate surface area ratio
    print('\t\tCalculating surface area ratio...')
    out_raster = Float(cell_area) / Cos(modified_slope)
    out_raster.save(area_output)
Пример #8
0
def main(in_raster=None, neighborhood_size=None, out_raster=None):
    """
    Compute terrain ruggedness, using the vector ruggedness measure (VRM),
    as described in:

        Sappington et al., 2007. Quantifying Landscape Ruggedness for
        Animal Habitat Analysis: A Case Study Using Bighorn Sheep in the
        Mojave Desert. Journal of Wildlife Management. 71(5): 1419 -1426.
    """
    hood_size = int(neighborhood_size)

    # FIXME: expose this as an option per #18
    w = utils.Workspace()
    if w.exists:
        out_workspace = w.path
    else:
        out_workspace = os.path.dirname(out_raster)
    utils.workspace_exists(out_workspace)
    # force temporary stats to be computed in our output workspace
    arcpy.env.scratchWorkspace = out_workspace
    arcpy.env.workspace = out_workspace

    # TODO expose as config
    pyramid_orig = arcpy.env.pyramid
    arcpy.env.pyramid = "NONE"
    # TODO: currently set to automatically overwrite, expose this as option
    arcpy.env.overwriteOutput = True
    arcpy.env.compression = 'LZW'

    try:
        # Create Slope and Aspect rasters
        utils.msg("Calculating aspect...")
        out_aspect = Aspect(in_raster)
        utils.msg("Calculating slope...")
        out_slope = Slope(in_raster, "DEGREE")

        # Convert Slope and Aspect rasters to radians
        utils.msg("Converting slope and aspect to radians...")
        slope_rad = out_slope * (math.pi / 180)
        aspect_rad = out_aspect * (math.pi / 180)

        # Calculate x, y, and z rasters
        utils.msg("Calculating x, y, and z rasters...")
        xy_raster_calc = Sin(slope_rad)
        z_raster_calc = Cos(slope_rad)
        x_raster_calc = Con(out_aspect == -1, 0,
                            Sin(aspect_rad)) * xy_raster_calc
        y_raster_calc = Con(out_aspect == -1, 0,
                            Cos(aspect_rad)) * xy_raster_calc

        # Calculate sums of x, y, and z rasters for selected neighborhood size
        utils.msg("Calculating sums of x, y, and z rasters in neighborhood...")
        hood = NbrRectangle(hood_size, hood_size, "CELL")
        x_sum_calc = FocalStatistics(x_raster_calc, hood, "SUM", "NODATA")
        y_sum_calc = FocalStatistics(y_raster_calc, hood, "SUM", "NODATA")
        z_sum_calc = FocalStatistics(z_raster_calc, hood, "SUM", "NODATA")

        # Calculate the resultant vector
        utils.msg("Calculating the resultant vector...")
        result_vect = (x_sum_calc**2 + y_sum_calc**2 + z_sum_calc**2)**0.5

        arcpy.env.rasterStatistics = "STATISTICS"
        arcpy.env.pyramid = pyramid_orig
        # Calculate the Ruggedness raster
        utils.msg("Calculating the final ruggedness raster...")
        ruggedness = 1 - (result_vect / hood_size**2)

        out_raster = utils.validate_path(out_raster)
        utils.msg("Saving ruggedness raster to to {}.".format(out_raster))
        arcpy.CopyRaster_management(ruggedness, out_raster)

    except Exception as e:
        utils.msg(e, mtype='error')
Пример #9
0
def main(in_raster=None, out_raster=None, acr_correction=True, area_raster=None):
    """
    A calculation of rugosity, based on the difference between surface
    area and planar area, as described in Jenness, J. 2002. Surface Areas
    and Ratios from Elevation Grid (surfgrids.avx) extension for ArcView 3.x,
    v. 1.2. Jenness Enterprises.

    NOTE: the VRM method implemented in ruggeddness is generally considered
          superior to this method.
    """

    # sanitize acr input
    if isinstance(acr_correction, str) and acr_correction.lower() == 'false':
        acr_correction = False

    w = utils.Workspace()
    if w.exists:
        out_workspace = w.path
    else:
        out_workspace = os.path.dirname(out_raster)
    # make sure workspace exists
    utils.workspace_exists(out_workspace)

    utils.msg("Set scratch workspace to {}...".format(out_workspace))

    # force temporary stats to be computed in our output workspace
    arcpy.env.scratchWorkspace = out_workspace
    arcpy.env.workspace = out_workspace
    pyramid_orig = arcpy.env.pyramid
    arcpy.env.pyramid = "NONE"
    # TODO: currently set to automatically overwrite, expose this as option
    arcpy.env.overwriteOutput = True

    bathy = Raster(in_raster)
    # get the cell size of the input raster; use same calculation as was
    # performed in BTM v1: (mean_x + mean_y) / 2
    cell_size = (bathy.meanCellWidth + bathy.meanCellHeight) / 2.0
    corner_dist = math.sqrt(2 * cell_size ** 2)
    flat_area = cell_size ** 2
    utils.msg("Cell size: {}\nFlat area: {}".format(cell_size, flat_area))

    try:
        # Create a set of shifted grids, with offets n from the origin X:

        #        8 | 7 | 6
        #        --|---|---
        #        5 | X | 4
        #        --|---|---
        #        3 | 2 | 1

        positions = [(1, -1), (0, -1), (-1, -1),
                     (1,  0),          (-1,  0),
                     (1,  1), (0,  1), (-1,  1)]

        corners = (1, 3, 6, 8)      # dist * sqrt(2), as set in corner_dist
        orthogonals = (2, 4, 5, 7)  # von Neumann neighbors, straight dist
        shift_rasts = [None]        # offset to align numbers
        temp_rasts = []

        for (n, pos) in enumerate(positions, start=1):
            utils.msg("Creating Shift Grid {} of 8...".format(n))
            # scale shift grid by cell size
            (x_shift, y_shift) = map(lambda n: n * cell_size, pos)

            # set explicit path on shift rasters, otherwise suffer
            # inexplicable 999999 errors.
            shift_out = os.path.join(out_workspace, "shift_{}.tif".format(n))
            shift_out = utils.validate_path(shift_out)
            temp_rasts.append(shift_out)
            arcpy.Shift_management(bathy, shift_out, x_shift, y_shift)
            shift_rasts.append(arcpy.sa.Raster(shift_out))

        edge_rasts = [None]
        # calculate triangle length grids

        # edges 1-8: pairs of bathy:shift[n]
        for (n, shift) in enumerate(shift_rasts[1:], start=1):
            utils.msg("Calculating Triangle Edge {} of 16...".format(n))
            # adjust for corners being sqrt(2) from center
            if n in corners:
                dist = corner_dist
            else:
                dist = cell_size
            edge_out = os.path.join(out_workspace, "edge_{}.tif".format(n))
            edge_out = utils.validate_path(edge_out)
            temp_rasts.append(edge_out)
            edge = compute_edge(bathy, shift, dist)
            edge.save(edge_out)
            edge_rasts.append(arcpy.sa.Raster(edge_out))

        # edges 9-16: pairs of adjacent shift grids [see layout above]
        # in BTM_v1, these are labeled A-H
        adjacent_shift = [(1, 2), (2, 3), (1, 4), (3, 5),
                          (6, 4), (5, 8), (6, 7), (7, 8)]
        for (n, pair) in enumerate(adjacent_shift, start=9):
            utils.msg("Calculating Triangle Edge {} of 16...".format(n))
            # the two shift rasters for this iteration
            (i, j) = pair
            edge_out = os.path.join(out_workspace, "edge_{}.tif".format(n))
            edge_out = utils.validate_path(edge_out)
            temp_rasts.append(edge_out)
            edge = compute_edge(shift_rasts[i], shift_rasts[j], cell_size)
            edge.save(edge_out)
            edge_rasts.append(arcpy.sa.Raster(edge_out))

        # areas of each triangle
        areas = []
        for (n, pair) in enumerate(adjacent_shift, start=1):
            utils.msg("Calculating Triangle Area {} of 8...".format(n))
            # the two shift rasters; n has the third side
            (i, j) = pair
            area_out = os.path.join(out_workspace, "area_{}.tif".format(n))
            area_out = utils.validate_path(area_out)
            temp_rasts.append(area_out)

            area = triangle_area(edge_rasts[i], edge_rasts[j], edge_rasts[n+8])
            area.save(area_out)
            areas.append(arcpy.sa.Raster(area_out))

        utils.msg("Summing Triangle Area...")
        arcpy.env.pyramid = pyramid_orig
        arcpy.env.rasterStatistics = "STATISTICS"
        arcpy.env.compression = "LZW"
        total_area = (areas[0] + areas[1] + areas[2] + areas[3] +
                      areas[4] + areas[5] + areas[6] + areas[7])
        if area_raster:
            save_msg = "Saving Surface Area Raster to " + \
                "{}.".format(area_raster)
            utils.msg(save_msg)
            arcpy.CopyRaster_management(total_area, area_raster)

        if not acr_correction:
            utils.msg("Calculating ratio with uncorrected planar area.")
            area_ratio = total_area / cell_size**2
        else:
            utils.msg("Calculating ratio with slope-corrected planar area.")
            slope_raster = arcpy.sa.Slope(in_raster, "DEGREE", "1")
            planar_area = Divide(float(cell_size**2),
                                 Cos(Times(slope_raster, 0.01745)))
            area_ratio = Divide(total_area, planar_area)

        out_raster = utils.validate_path(out_raster)
        save_msg = "Saving Surface Area to Planar Area ratio to " + \
            "{}.".format(out_raster)
        utils.msg(save_msg)
        arcpy.CopyRaster_management(area_ratio, out_raster)

    except Exception as e:
        utils.msg(e, mtype='error')

    try:
        # Delete all intermediate raster data sets
        utils.msg("Deleting intermediate data...")
        for path in temp_rasts:
            arcpy.Delete_management(path)

    except Exception as e:
        utils.msg(e, mtype='error')