示例#1
0
    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
示例#2
0
def do_score(fire, year, day, p, shp):
    """!
    Calculate score 
    @param fire Fire to calculate score for
    @param year Year fire is from
    @param day Day score is for
    @param p Probability raster to compare to
    @param shp Shapefile for actual perimeter
    @return None
    """
    orig_raster = os.path.join(run_output, fire + ".tif")
    orig_raster = Raster(orig_raster) if os.path.exists(orig_raster) else None
    prob_raster = Raster(p)
    raster = os.path.join(run_output,
                          os.path.splitext(os.path.basename(shp))[0] + '.tif')
    perim, raster = rasterize_perim(run_output, shp, year, fire, raster)
    if perim:
        target = Raster(raster)
        # remove the original raster used to start the simulation
        r = Con(IsNull(orig_raster), prob_raster,
                0.0) if orig_raster is not None else prob_raster
        r = SetNull(r == 0.0, r)
        m = Con(IsNull(orig_raster), target,
                0.0) if orig_raster is not None else target
        m = SetNull(m == 0.0, m)
        hits = Con(IsNull(r), 0.0, r) * Con(IsNull(m), 0.0, 1.0)
        misses = Con(IsNull(r), 1.0, 0.0) * Con(IsNull(m), 0.0, 1.0)
        false_positives = Con(IsNull(r), 0.0, r) * Con(IsNull(m), 1.0, 0.0)
        tp = arcpy.RasterToNumPyArray(hits, nodata_to_value=0).sum()
        fn = arcpy.RasterToNumPyArray(misses, nodata_to_value=0).sum()
        fp = arcpy.RasterToNumPyArray(false_positives, nodata_to_value=0).sum()
        total_score = tp / (tp + fn + fp)
        #~ logging.info("Scores are {} + {} + {} = {}".format(tp, fn, fp, total_score))
        scores.append([fire, year, day, p, shp, tp, fn, fp, total_score])
示例#3
0
def CalcZonalStats(in_zone_data, zone_field, in_value_raster, out_table):
    """
    Resamples inValueRaster to 5m pixel size and calculates the average value
    within each map unit. Higher resolution required for map units <5 acres.
    :param in_zone_data: the Map Units Dissolve feature class
    :param zone_field: the field to use as zone field, must be integer and
    cannot be OBJECTID
    :param in_value_raster: raster dataset or basename as a string
    :param out_table: a name to save the ouput table as a string
    :return: None
    """
    # Convert null values to 0 so that they are not ignored when summarizing
    in_value_raster = Con(IsNull(in_value_raster),0,in_value_raster)

    # Resample to avoid small map units returning null values
    resample = True
    if resample:
        # Resample raster
        tmp_raster = "sub_raster"
        arcpy.Resample_management(in_value_raster, tmp_raster, "5", "NEAREST")
    else:
        tmp_raster = in_value_raster
    # Calculate zonal statistics
    arcpy.gp.ZonalStatisticsAsTable_sa(in_zone_data, zone_field, tmp_raster,
                                    out_table, "DATA", "MEAN")
    if resample:
        arcpy.Delete_management(tmp_raster)
示例#4
0
def combineProposedWithCurrentDebit(anthroPath, uniqueProposedSubtypes):
    for subtype in uniqueProposedSubtypes:
        # Merge proposed and current feature rasters
        currentAnthroFeature = Raster(os.path.join(anthroPath, subtype))
        proposedAnthroFeature = Raster("Proposed_" + subtype)
        postAnthroFeature = Con(IsNull(proposedAnthroFeature),
                                currentAnthroFeature, proposedAnthroFeature)
        postAnthroFeature.save(os.path.join("Post_" + subtype))
示例#5
0
def create_mask(path_to_temp):
    arcpy.CheckOutExtension('Spatial')
    inputrasters = arcpy.GetParameterAsText(1).split(";")
    rasterlist = []
    for elements in inputrasters:
        rasterobject = Raster(elements)
        rasterlist.append(rasterobject)
    rasterlistSum = sum(rasterlist)                     
    outcon = Con(IsNull(rasterlistSum) == 0,1)          # result raster has 1 when value meets value and NoData when value meets NoData
    outcon.save(join(path_to_temp,"mask"))              # filename is 'mask'
    #arcpy.CheckInExtension('Spatial')                  
    path_to_mask = join(path_to_temp,"mask")
    if arcpy.Exists(path_to_mask):
        arcpy.AddMessage("Creating mask.")
    return path_to_mask
示例#6
0
def calcConiferPost(coniferTreatmentArea, Conifer_Cover):
    arcpy.AddMessage("Calculating post-project conifer modifier")
    # Add field Conifer to use when converting to raster
    inTable = coniferTreatmentArea
    fieldName = "Conifer"
    fieldType = "SHORT"
    expression = 0
    arcpy.AddField_management(inTable, fieldName, fieldType)
    arcpy.CalculateField_management(inTable, fieldName, expression,
                                    "PYTHON_9.3", "")

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

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

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

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

    coniferCover400 = FocalStatistics(in_raster, neighborhood, statistics_type)

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

    return coniferModifierPost
示例#7
0
def function(DEM, streamNetwork, smoothDropBuffer, smoothDrop, streamDrop, outputReconDEM):

    try:
        # Set environment variables
        arcpy.env.extent = DEM
        arcpy.env.mask = DEM
        arcpy.env.cellSize = DEM

        # Set temporary variables
        prefix = "recon_"
        streamRaster = prefix + "streamRaster"

        # Determine DEM cell size and OID column name
        size = arcpy.GetRasterProperties_management(DEM, "CELLSIZEX")
        OIDField = arcpy.Describe(streamNetwork).OIDFieldName

        # Convert stream network to raster
        arcpy.PolylineToRaster_conversion(streamNetwork, OIDField, streamRaster, "", "", size)

        # Work out distance of cells from stream
        distanceFromStream = EucDistance(streamRaster, "", size)

        # Elements within a buffer distance of the stream are smoothly dropped
        intSmoothDrop = Con(distanceFromStream > float(smoothDropBuffer), 0,
                            (float(smoothDrop) / float(smoothDropBuffer)) * (float(smoothDropBuffer) - distanceFromStream))
        del distanceFromStream

        # Burn this smooth drop into DEM. Cells in stream are sharply dropped by the value of "streamDrop"
        binaryStream = Con(IsNull(Raster(streamRaster)), 0, 1)
        reconDEMTemp = Raster(DEM) - intSmoothDrop - (float(streamDrop) * binaryStream)
        del intSmoothDrop
        del binaryStream
        
        reconDEMTemp.save(outputReconDEM)
        del reconDEMTemp

        log.info("Reconditioned DEM generated")

    except Exception:
        log.error("DEM reconditioning function failed")
        raise
def merge_spectral_tiles(**kwargs):
    """
    Description: extracts spectral tiles to an area and mosaics extracted tiles with first data priority
    Inputs: 'cell_size' -- a cell size for the output spectral raster
            'output_projection' -- the machine number for the output projection
            'work_geodatabase' -- a geodatabase to store temporary results
            'input_array' -- an array containing the grid raster (must be first), the study area raster (must be second), and the list of spectral tiles
            'output_array' -- an array containing the output spectral grid raster
    Returned Value: Returns a raster dataset on disk containing the merged spectral grid raster
    Preconditions: requires processed source spectral tiles and predefined grid
    """

    # Import packages
    import arcpy
    from arcpy.sa import ExtractByMask
    from arcpy.sa import IsNull
    from arcpy.sa import Nibble
    from arcpy.sa import Raster
    from arcpy.sa import SetNull
    import datetime
    import os
    import time

    # Parse key word argument inputs
    cell_size = kwargs['cell_size']
    output_projection = kwargs['output_projection']
    work_geodatabase = kwargs['work_geodatabase']
    tile_inputs = kwargs['input_array']
    grid_raster = tile_inputs.pop(0)
    study_area = tile_inputs.pop(0)
    spectral_grid = kwargs['output_array'][0]

    # 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 = study_area
    arcpy.env.extent = Raster(grid_raster).extent

    # Define the output coordinate system
    output_system = arcpy.SpatialReference(output_projection)

    # Define intermediate rasters
    mosaic_raster = os.path.splitext(spectral_grid)[0] + '_mosaic.tif'
    nibble_raster = os.path.splitext(spectral_grid)[0] + '_nibble.tif'
    spectral_area = os.path.splitext(spectral_grid)[0] + '_area.tif'

    # Define folder structure
    grid_title = os.path.splitext(os.path.split(grid_raster)[1])[0]
    mosaic_location, mosaic_name = os.path.split(mosaic_raster)

    # Create source folder within mosaic location if it does not already exist
    source_folder = os.path.join(mosaic_location, 'sources')
    if os.path.exists(source_folder) == 0:
        os.mkdir(source_folder)

    # Create an empty list to store existing extracted source rasters for the grid
    input_length = len(tile_inputs)
    input_rasters = []

    # Identify raster extent of grid
    print(f'\tExtracting {input_length} spectral tiles...')
    grid_extent = Raster(grid_raster).extent
    grid_array = arcpy.Array()
    grid_array.add(arcpy.Point(grid_extent.XMin, grid_extent.YMin))
    grid_array.add(arcpy.Point(grid_extent.XMin, grid_extent.YMax))
    grid_array.add(arcpy.Point(grid_extent.XMax, grid_extent.YMax))
    grid_array.add(arcpy.Point(grid_extent.XMax, grid_extent.YMin))
    grid_array.add(arcpy.Point(grid_extent.XMin, grid_extent.YMin))
    grid_polygon = arcpy.Polygon(grid_array)

    # Save grid polygon
    grid_feature = os.path.join(work_geodatabase, 'grid_polygon')
    arcpy.management.CopyFeatures(grid_polygon, grid_feature)
    arcpy.management.DefineProjection(grid_feature, output_system)

    # Iterate through all input tiles and extract to grid if they overlap
    count = 1
    for raster in tile_inputs:
        output_raster = os.path.join(source_folder, os.path.split(raster)[1])
        if os.path.exists(output_raster) == 0:
            # Identify raster extent of tile
            tile_extent = Raster(raster).extent
            tile_array = arcpy.Array()
            tile_array.add(arcpy.Point(tile_extent.XMin, tile_extent.YMin))
            tile_array.add(arcpy.Point(tile_extent.XMin, tile_extent.YMax))
            tile_array.add(arcpy.Point(tile_extent.XMax, tile_extent.YMax))
            tile_array.add(arcpy.Point(tile_extent.XMax, tile_extent.YMin))
            tile_array.add(arcpy.Point(tile_extent.XMin, tile_extent.YMin))
            tile_polygon = arcpy.Polygon(tile_array)

            # Save tile polygon
            tile_feature = os.path.join(work_geodatabase, 'tile_polygon')
            arcpy.CopyFeatures_management(tile_polygon, tile_feature)
            arcpy.DefineProjection_management(tile_feature, output_system)

            # Select tile extent with grid extent
            selection = int(
                arcpy.GetCount_management(
                    arcpy.management.SelectLayerByLocation(
                        tile_feature, 'INTERSECT', grid_feature, '',
                        'NEW_SELECTION', 'NOT_INVERT')).getOutput(0))

            # If tile overlaps grid then perform extraction
            if selection == 1:
                # Extract raster to mask
                print(
                    f'\t\tExtracting spectral tile {count} of {input_length}...'
                )
                iteration_start = time.time()
                extract_raster = ExtractByMask(raster, grid_raster)
                # Copy extracted raster to output
                print(f'\t\tSaving spectral tile {count} of {input_length}...')
                arcpy.management.CopyRaster(extract_raster, output_raster, '',
                                            '0', '-32768', 'NONE', 'NONE',
                                            '16_BIT_SIGNED', 'NONE', 'NONE',
                                            'TIFF', 'NONE', 'CURRENT_SLICE',
                                            'NO_TRANSPOSE')
                # End timing
                iteration_end = time.time()
                iteration_elapsed = int(iteration_end - iteration_start)
                iteration_success_time = datetime.datetime.now()
                # Report success
                print(
                    f'\t\tCompleted at {iteration_success_time.strftime("%Y-%m-%d %H:%M")} (Elapsed time: {datetime.timedelta(seconds=iteration_elapsed)})'
                )
                print('\t\t----------')
            # If tile does not overlap grid then report message
            else:
                print(
                    f'\t\tSpectral tile {count} of {input_length} does not overlap grid...'
                )
                print('\t\t----------')

            # Remove tile feature class
            if arcpy.Exists(tile_feature) == 1:
                arcpy.management.Delete(tile_feature)

        # If extracted tile already exists then report message
        else:
            print(
                f'\t\tExtracted spectral tile {count} of {input_length} already exists...'
            )
            print('\t\t----------')

        # If the output raster exists then append it to the raster list
        if os.path.exists(output_raster) == 1:
            input_rasters.append(output_raster)
        count += 1

    # Remove grid feature
    if arcpy.Exists(grid_feature) == 1:
        arcpy.management.Delete(grid_feature)
    print(f'\tFinished extracting {input_length} spectral tiles.')
    print('\t----------')

    # Mosaic raster tiles to new raster
    print(f'\tMosaicking the input rasters for {grid_title}...')
    iteration_start = time.time()
    arcpy.management.MosaicToNewRaster(input_rasters, mosaic_location,
                                       mosaic_name, output_system,
                                       '16_BIT_SIGNED', cell_size, '1',
                                       'MAXIMUM', 'FIRST')
    # Enforce correct projection
    arcpy.management.DefineProjection(mosaic_raster, output_system)
    # 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----------')

    # Calculate the missing area
    print('\tCalculating null space...')
    iteration_start = time.time()
    raster_null = SetNull(IsNull(Raster(mosaic_raster)), 1, 'VALUE = 1')
    # 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----------')

    # Impute missing data by nibbling the NoData from the focal mean
    print('\tImputing missing values by geographic nearest neighbor...')
    iteration_start = time.time()
    raster_filled = Nibble(Raster(mosaic_raster), raster_null, 'DATA_ONLY',
                           'PROCESS_NODATA', '')
    # Copy nibble raster to output
    print(f'\tSaving filled raster...')
    arcpy.management.CopyRaster(raster_filled, nibble_raster, '', '0',
                                '-32768', 'NONE', 'NONE', '16_BIT_SIGNED',
                                'NONE', 'NONE', 'TIFF', 'NONE',
                                'CURRENT_SLICE', 'NO_TRANSPOSE')
    # 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----------')

    # Remove overflow fill from the study area
    print('\tRemoving overflow fill from study area...')
    iteration_start = time.time()
    raster_preliminary = ExtractByMask(nibble_raster, study_area)
    # Copy preliminary extracted raster to output
    arcpy.management.CopyRaster(raster_preliminary, spectral_area, '', '0',
                                '-32768', 'NONE', 'NONE', '16_BIT_SIGNED',
                                'NONE', 'NONE', 'TIFF', 'NONE',
                                'CURRENT_SLICE', 'NO_TRANSPOSE')
    # 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----------')

    # Remove overflow fill from the grid
    print('\tRemoving overflow fill from grid...')
    iteration_start = time.time()
    raster_final = ExtractByMask(spectral_area, grid_raster)
    arcpy.management.CopyRaster(raster_final, spectral_grid, '', '0', '-32768',
                                'NONE', 'NONE', '16_BIT_SIGNED', 'NONE',
                                'NONE', 'TIFF', 'NONE', 'CURRENT_SLICE',
                                'NO_TRANSPOSE')
    # Delete intermediate rasters
    if arcpy.Exists(mosaic_raster) == 1:
        arcpy.management.Delete(mosaic_raster)
    if arcpy.Exists(nibble_raster) == 1:
        arcpy.management.Delete(nibble_raster)
    if arcpy.Exists(spectral_area) == 1:
        arcpy.management.Delete(spectral_area)
    # 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----------')
    out_process = f'Successfully created {os.path.split(spectral_grid)[1]}'
    return out_process
def get_path_residence_times (in_file, cost_rast, out_raster, t_diff_fld_name, workspace):
    
    if len (out_raster) == 0:
        arcpy.AddError ("Missing argument: out_rast")
        raise Exception
    if len (t_diff_fld_name) == 0:
        t_diff_fld_name = "T_DIFF_HRS"

    arcpy.env.overwriteOutput = True  #  This is underhanded.  It should be an argument.

    if arcpy.env.outputCoordinateSystem is None:
        arcpy.env.outputCoordinateSystem = cost_rast
    arcpy.AddMessage ("coordinate system is %s" % arcpy.env.outputCoordinateSystem.name)

    if len(workspace):
        arcpy.env.workspace = workspace
    if arcpy.env.workspace is None or len(arcpy.env.workspace) == 0:
        arcpy.env.workspace = os.getcwd()

    if '.gdb' in arcpy.env.workspace:
        arcpy.AddError (
            "Worskpace is a geodatabase.  " +
            "This brings too much pain for this script to work.\n" +
            "%s" % arcpy.env.workspace
        )
        raise WorkspaceIsGeodatabase


    r = Raster(cost_rast)
    
    if r.maximum == 0 and r.minimum == 0:
        arcpy.AddMessage ('Cost raster has only zero value.  Cannot calculate cost distances.')
        raise CostRasterIsZero

    size = r.height * r.width * 4
    if size > 2 * 1028 ** 3:
        import struct
        struct_size = struct.calcsize("P") * 8
        if struct_size == 32:
            size_in_gb = float (size) / (1028 ** 3)
            arcpy.AddMessage (
                'Cost raster exceeds 2 GiB in size (%s GiB).  This is too large for a 32 bit NumPy.' % size_in_gb
            )
            raise NumPyArrayExceedsSizeLimits

    if not check_points_are_in_cost_raster(in_file, cost_rast):
        arcpy.AddError ('One or more input points do not intersect the cost raster')
        raise PointNotOnRaster

    arcpy.env.snapRaster = cost_rast
    suffix = None
    wk = arcpy.env.workspace
    if not '.gdb' in wk:
        suffix = '.shp'


    ext = arcpy.env.extent
    if ext is None:
        arcpy.env.extent = r.extent

    arcpy.AddMessage ("Extent is %s" % arcpy.env.extent)

    arcpy.env.cellSize = r.meanCellWidth
    arcpy.AddMessage ("Cell size is %s" % arcpy.env.cellSize)
    cellsize_used = float (arcpy.env.cellSize)
    extent = arcpy.env.extent
    lower_left_coord = extent.lowerLeft
    
    arcpy.AddMessage ('Currently in directory: %s\n' % os.getcwd())
    arcpy.AddMessage ('Workspace is: %s' % arcpy.env.workspace)
    arcpy.AddMessage ("lower left is %s" % lower_left_coord)

    if arcpy.env.mask is None:
        arcpy.AddMessage ("Setting mask to %s" % cost_rast)
        arcpy.env.mask = cost_rast

    #  accumulated transits
    transit_array_accum = arcpy.RasterToNumPyArray (Raster(cost_rast) * 0)

    feat_layer = "feat_layer"
    arcmgt.MakeFeatureLayer(in_file, feat_layer)
    desc = arcpy.Describe (feat_layer)
    oid_fd_name = desc.OIDFieldName
    arcpy.AddMessage("oid_fd_name = %s" % oid_fd_name)

    #  variable name is redundant now??? - should all calls be to oid_fd_name?
    target_fld = oid_fd_name

    proc_layer = "process_layer"
    arcmgt.MakeFeatureLayer(in_file, proc_layer)
    rows = arcpy.SearchCursor(proc_layer)
    last_target = None

    for row_cur in rows:
        transit_time = row_cur.getValue (t_diff_fld_name)

        if last_target is None or transit_time == 0:
            message = 'Skipping %s = %s' % (oid_fd_name, row_cur.getValue(oid_fd_name))
            if transit_time == 0:
                message = message + "  Transit time is zero"
            arcpy.AddMessage(message)
            last_target = row_cur.getValue(target_fld)
            last_oid    = row_cur.getValue(oid_fd_name)
            continue

        arcpy.AddMessage ("Processing %s %i" % (oid_fd_name, row_cur.getValue(oid_fd_name)))

        arcmgt.SelectLayerByAttribute(
            feat_layer,
            "NEW_SELECTION",
            '%s = %s' % (target_fld, last_target)
        )
        backlink_rast  = arcpy.CreateScratchName("backlink")
        path_dist_rast = PathDistance(feat_layer, cost_rast, out_backlink_raster = backlink_rast)

        #  extract the distance from the last point
        shp = row_cur.shape
        centroid = shp.centroid
        (x, y) = (centroid.X, centroid.Y)
        result = arcmgt.GetCellValue(path_dist_rast, "%s %s" % (x, y), "1")
        res_val = result.getOutput(0)
        if res_val == "NoData":
            this_oid = row_cur.getValue(oid_fd_name)
            arcpy.AddMessage ("Got nodata for coordinate (%s, %s)" % (x, y))
            arcpy.AddMessage ("Is the path between features %s and %s wholly contained by the cost raster?" % (last_oid, this_oid))
            pras_name = "pth_%s_%s.tif" % (last_oid, this_oid)
            arcpy.AddMessage ("Attempting to save path raster as %s" % pras_name)
            try:
                path_dist_rast.save(pras_name)
            except Exception as e:
                arcpy.AddMessage (e)
            raise PathDistanceIsNoData
        try:
            path_distance = float (res_val)
        except:
            #  kludge around locale/radix issues 
            if res_val.find(","):
                res_val = res_val.replace(",", ".")
                path_distance = float (res_val)
            else:
                raise
        arcpy.AddMessage("Path distance is %s\nTransit time is %s" % (path_distance, transit_time))

        #  get a raster of the path from origin to destination
        condition = '%s in (%i, %i)' % (oid_fd_name, last_oid, row_cur.getValue(oid_fd_name))
        dest_layer = "dest_layer" + str (last_oid)
        arcmgt.MakeFeatureLayer(in_file, dest_layer, where_clause = condition)

        count = arcmgt.GetCount(dest_layer)
        count = int (count.getOutput(0))
        if count == 0:
            raise NoFeatures("No features selected.  Possible coordinate system issues.\n" + condition)

        try:
            path_cost_rast = CostPath(dest_layer, path_dist_rast, backlink_rast)
            #path_dist_rast.save("xx_pr" + str (last_oid))
        except Exception as e:
            raise

        try:
            pcr_mask       = 1 - IsNull (path_cost_rast)
            #pcr_mask.save ("xx_pcr_mask" + str (last_oid))
            dist_masked    = path_dist_rast * pcr_mask
            path_array     = arcpy.RasterToNumPyArray(dist_masked, nodata_to_value = -9999)
            path_array_idx = numpy.where(path_array > 0)
            transit_array  = numpy.zeros_like(path_array)  #  past experience suggests we might need to use a different approach to guarantee we get zeroes
        except:
            raise

        path_sum = None
        arcpy.AddMessage ("processing %i cells of path raster" % (len(path_array_idx[0])))

        if path_distance == 0 or not len(path_array_idx[0]):
            path_sum = 1 #  stayed in the same cell
            mask_array = arcpy.RasterToNumPyArray(pcr_mask, nodata_to_value = -9999)
            mask_array_idx = numpy.where(mask_array == 1)
            i = mask_array_idx[0][0]
            j = mask_array_idx[1][0]
            transit_array[i][j] = path_sum
        else:
            row_count = len (path_array) 
            col_count = len (path_array[0])

            for idx in range (len(path_array_idx[0])):
                i = path_array_idx[0][idx]
                j = path_array_idx[1][idx]
                val = path_array[i][j]
                nbrs = []
                for k in (i-1, i, i+1):
                    if k < 0 or k >= row_count:
                        continue
                    checkrow = path_array[k]
                    for l in (j-1, j, j+1):
                        if l < 0 or l >= col_count:
                            continue
                        if k == i and j == l:
                            continue  #  don't check self
                        checkval = checkrow[l]
                        #  negs are nodata, and this way we
                        #  don't need to care what that value is
                        if checkval >= 0:
                            diff = val - checkval
                            if diff > 0:
                                nbrs.append(diff)
                                #arcpy.AddMessage ("Check and diff vals are %s %s" % (checkval, diff))
                diff = min (nbrs)
                #arcpy.AddMessage ("Diff  val is %s" % diff)
                transit_array[i][j] = diff

            path_sum = path_array.max()  #  could use path_distance?
            #arcpy.AddMessage ("path_array.max is %s" % path_sum)

        #  sometimes we get a zero path_sum even when the path_distance is non-zero
        if path_sum == 0:
            path_sum = 1

        #  Increment the cumulative transit array by the fraction of the
        #  transit time spent in each cell.
        #  Use path_sum because it corrects for cases where we stayed in the same cell.
        transit_array_accum = transit_array_accum + ((transit_array / path_sum) * transit_time)

        #xx = arcpy.NumPyArrayToRaster (transit_array, lower_left_coord, cellsize_used, cellsize_used, 0)
        #tmpname = "xx_t_arr_" + str (last_oid)
        #print "Saving transit array to %s" % tmpname
        #xx.save (tmpname)


        try:
            arcmgt.Delete(backlink_rast)
            arcmgt.Delete(dest_layer)
        except Exception as e:
            arcpy.AddMessage (e)

        #  getting off-by-one errors when using the environment, so use this directly
        ext = path_cost_rast.extent
        lower_left_coord = ext.lowerLeft

        last_target = row_cur.getValue(target_fld)
        last_oid    = row_cur.getValue(oid_fd_name)

    #  need to use env settings to get it to be the correct size
    try:
        arcpy.AddMessage ("lower left is %s" % lower_left_coord)
        xx = arcpy.NumPyArrayToRaster (transit_array_accum, lower_left_coord, cellsize_used, cellsize_used, 0)
        print "Saving to %s" % out_raster
        xx.save (out_raster)
    except:
        raise


    print "Completed"

    return ()
示例#10
0
def arc_catch_del(WD, boundary_shp, sites_shp, site_num_col='site', point_dis=1000, stream_depth=10, grid_size=8, pour_dis=20, streams='S:/Surface Water/shared\\GIS_base\\vector\\MFE_REC_rivers_no_1st.shp', dem='S:/Surface Water/shared\\GIS_base\\raster\\DEM_8m_2012\\linz_8m_dem', export_dir='results', overwrite_rasters=False):
    """
    Arcpy function to delineate catchments based on specific points, a polygon, and the REC rivers layer.
    Arcpy must be installed.
    Be careful that the folder path isn't too long!!! Do not have spaces in the path name!!! Arc sucks!!!

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

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

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

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

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

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

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

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

    ### Parameters:
    ## input

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

#    site_num_col = 'site'

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

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

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

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

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

    ### Process sites and streams vectors

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    #### Check back in the spatial analyst license once done
    arcpy.CheckInExtension('Spatial')
def convert_fire_history(**kwargs):
    """
    Description: converts fire history polygons to rasters and extracts to major grid and study area
    Inputs: 'work_geodatabase' -- path to a file geodatabase that will serve as the workspace
            'input_array' -- an array containing the target feature class to convert (must be first), the study area raster (must be second), and the grid raster (must be third)
            'output_array' -- an array containing the output raster
    Returned Value: Returns a raster dataset
    Preconditions: the target feature class must be created using the recent fire history function
    """

    # Import packages
    import arcpy
    from arcpy.sa import Con
    from arcpy.sa import ExtractByMask
    from arcpy.sa import IsNull
    from arcpy.sa import Raster
    import datetime
    import time
    import os

    # Parse key word argument inputs
    work_geodatabase = kwargs['work_geodatabase']
    input_feature = kwargs['input_array'][0]
    study_area = kwargs['input_array'][1]
    grid_raster = kwargs['input_array'][2]
    output_raster = kwargs['output_array'][0]

    # Set overwrite option
    arcpy.env.overwriteOutput = True

    # Set workspace
    arcpy.env.workspace = work_geodatabase

    # Set snap raster and extent
    arcpy.env.snapRaster = study_area
    arcpy.env.extent = Raster(grid_raster).extent
    arcpy.env.cellSize = 'MINOF'

    # Define intermediate rasters
    convert_raster = os.path.splitext(output_raster)[0] + '.tif'

    # Convert fire history feature class to raster
    print('\tConverting feature class to raster within grid...')
    iteration_start = time.time()
    arcpy.conversion.PolygonToRaster(input_feature, 'FireYear', convert_raster, 'CELL_CENTER', 'FireYear', 10)
    # 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----------')

    # Convert no data values to zero
    print('\tConverting no data to zero...')
    iteration_start = time.time()
    zero_raster = Con(IsNull(Raster(convert_raster)), 0, Raster(convert_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----------')

    # Extract raster to study area
    print(f'\tExtracting raster to grid...')
    iteration_start = time.time()
    extract1_raster = ExtractByMask(zero_raster, grid_raster)
    print(f'\tExtracting raster to study area...')
    extract2_raster = ExtractByMask(extract1_raster, study_area)
    print(f'\tCopying extracted raster to new raster...')
    arcpy.management.CopyRaster(extract2_raster,
                                output_raster,
                                '',
                                '',
                                '-32768',
                                'NONE',
                                'NONE',
                                '16_BIT_SIGNED',
                                'NONE',
                                'NONE',
                                'TIFF',
                                'NONE',
                                'CURRENT_SLICE',
                                'NO_TRANSPOSE'
                                )
    # 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----------')
    out_process = f'Successfully extracted recent fire history to study area.'
    return out_process
示例#12
0
def main():
    # GET PARAMETER VALUES
    Map_Units_Provided = arcpy.GetParameterAsText(0)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    # # Calculate Area
    # hqtlib.CalcAcres(Map_Units_Dissolve)

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

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

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

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

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

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

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

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

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

    seasonalHabitatRasters = [LSDMWinterPre, LSDMBreedingPre, LSDMSummerPre]

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

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

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

    seasonalHabitatRasters = [LSDMWinterPost, LSDMBreedingPost, LSDMSummerPost]

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

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

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

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

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

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

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

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

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

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

    # Clean up
    arcpy.Delete_management("in_memory")

    # Save map document
    if arcpy.ListInstallations()[0] == 'arcgispro':
        p = arcpy.mp.ArcGISProject("CURRENT")
        p.save()
    else:
        mxd = arcpy.mapping.MapDocument("CURRENT")
        mxd.save()
示例#13
0
def convertProposedToRasterCredit(anthroFeaturesRemoved, cellSize):
    arcpy.AddMessage("Preparing Proposed Surface Disturbance for processing")
    # Add field Conifer to use when converting to raster
    inTable = anthroFeaturesRemoved
    fieldName = "Weight2"
    fieldType = "SHORT"
    expression = 1
    arcpy.AddField_management(inTable, fieldName, fieldType)
    arcpy.CalculateField_management(inTable, fieldName, expression, "PYTHON_9.3", "")

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

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

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

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

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

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

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

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

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

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

    return uniqueProposedSubtypes
示例#14
0
def interpolate_raster(**kwargs):
    """
    Description: interpolates missing raster data using nearest existing raster data
    Inputs: 'input_array' -- an array containing the study area raster (must be first) and the climate raster (last)
            'output_array' -- an array containing the output climate raster for the grid
    Returned Value: Returns a raster dataset on disk containing the combined climate property for a grid
    Preconditions: requires an input grid raster and climate property raster
    """

    # Import packages
    import arcpy
    from arcpy.sa import IsNull
    from arcpy.sa import Nibble
    from arcpy.sa import Raster
    from arcpy.sa import SetNull
    import datetime
    import time

    # Parse key word argument inputs
    study_area = kwargs['input_array'][0]
    climate_raster = kwargs['input_array'][1]
    output_raster = kwargs['output_array'][0]

    # Set overwrite option
    arcpy.env.overwriteOutput = True

    # Set snap raster and extent
    arcpy.env.snapRaster = climate_raster
    arcpy.env.cellSize = 'MINOF'
    arcpy.env.extent = Raster(study_area).extent

    # Interpolate missing data from the climate raster
    print('\tCalculating null space...')
    iteration_start = time.time()
    raster_null = SetNull(IsNull(Raster(climate_raster)), 1, 'VALUE = 1')
    print(f'\tInterpolating missing data...')
    nibble_raster = Nibble(Raster(climate_raster), raster_null, 'DATA_ONLY',
                           'PROCESS_NODATA', '')
    # 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----------')

    # Export interpolated raster to output raster
    print(f'\tExporting interpolated raster to output raster...')
    iteration_start = time.time()
    arcpy.management.CopyRaster(nibble_raster, output_raster, '', '', '-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----------')
    out_process = f'Finished interpolating raster.'
    return out_process
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