def topographic_position(elevation_input, position_output):
    """
    Description: calculates 32-bit float topographic position
    Inputs: 'elevation_input' -- an input raster digital elevation model
            'relief_output' -- an output surface relief ratio raster
    Returned Value: Returns a raster dataset on disk
    Preconditions: requires an input elevation raster
    """

    # Import packages
    import arcpy
    from arcpy.sa import FocalStatistics
    from arcpy.sa import NbrRectangle
    from arcpy.sa import Raster

    # Set overwrite option
    arcpy.env.overwriteOutput = True

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

    # Calculate local mean
    print('\t\tCalculating local mean...')
    local_mean = FocalStatistics(elevation_input, neighborhood, 'MEAN', 'DATA')

    # Calculate topographic position
    print('\t\tCalculating topographic position...')
    out_raster = Raster(elevation_input) - local_mean
    out_raster.save(position_output)
def make_weightrasters():
    ap.Project_management(INPUTPOLYS,TMPPOLYS,ap.SpatialReference(OUTCOORDS))
    ap.AddField_management(TMPPOLYS,"__area","DOUBLE")
    ap.AddField_management(TMPPOLYS,"__normalized","DOUBLE")
    ap.CalculateField_management(TMPPOLYS,"__area","!shape.area@kilometers!","PYTHON")
    ret = []
    for f in RASTERFIELDS:
        ap.CalculateField_management(TMPPOLYS,"__normalized","!%s!/!__area!"%f,"PYTHON")
        ap.PolygonToRaster_conversion(TMPPOLYS,"__normalized",f,cellsize=OUTRES)
        distributed = Raster(f) * Raster(DISTRASTERS[f])
        out = "d%s"%f
        distributed.save(out)
        ret.append(out)
    
    return ret
Exemple #3
0
def calculate_LST(source_dir):
    dir_name = os.path.dirname(source_dir)
    basename = os.path.basename(source_dir)
    print(dir_name, basename)
    workspace = create_dir(basename + ".gdb")
    print workspace
    env.workspace = workspace
    env.overwriteOutput = True
    Band4 = "{}/{}_B4.tif".format(source_dir, basename)
    Band5 = "{}/{}_B5.tif".format(source_dir, basename)
    Band10 = "{}/{}_B10.tif".format(source_dir, basename)

    Band4_R = Raster(Band4)
    Band5_R = Raster(Band5)
    Band5_R.save("{}/{}_bands".format(workspace, basename))

    Band4 = Float(Band4_R)
    Band5 = Float(Band5_R)
    Band10 = Float(Raster(Band10))

    NDVI = Divide((Band5 - Band4), (Band5 + Band4))
    NDVI_path = "{}/{}_ndvi".format(workspace, basename)
    print NDVI_path
    NDVI.save(NDVI_path)

    NDVI_max = GetRasterProperties_management(
        NDVI_path, property_type="MAXIMUM").getOutput(0)
    NDVI_min = GetRasterProperties_management(
        NDVI_path, property_type="MINIMUM").getOutput(0)
    a = Minus(NDVI, -1)
    b = float(NDVI_max) - float(NDVI_min)
    c = Divide(a, b)
    PV = Square(c)
    E = 0.004 * PV + 0.986
    E.save("{}/{}_E".format(workspace, basename))

    TOA = 0.0003342 * Band10 + 0.1
    BT = 1321.08 / Ln((774.89 / TOA) + 1) - 273.15
    d = 1 + (0.00115 * BT / 1.4388) + Ln(E)
    LST = Divide(BT, d)
    print LST, type(LST)
    LST_Path = "{}/{}_LST".format(workspace, basename)
    LST.save(LST_Path)
    print(LST_Path)
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
Exemple #5
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')
            output_raster.GetRasterBand(1).WriteArray(
                grid_z)  # Writes my array to the raster
            output_raster.FlushCache()
            output_raster = None

            ## clipping
            arcpy.Clip_management('VOD_LPDR2_%s_%03d_%s.tif' %(year,date,pass_type), \
                                  "#",'VOD_LPDR2_%s_%03d_%s_clip.tif' %(year,date,pass_type),\
                                   Dir_CA+'/'+"CA.shp", "0", "ClippingGeometry")
            #            ##mapping algebra * 1
            inRaster = 'VOD_LPDR2_%s_%03d_%s_clip.tif' % (year, date,
                                                          pass_type)

            outRaster = Raster(inRaster) * map_factor
            outRaster.save(Dir_fig + '/' +
                           'VOD_LPDR2_%s_%03d_%s_clip_map.tif' %
                           (year, date, pass_type))
            #copy raster
            inRaster = outRaster

            arcpy.CopyRaster_management(inRaster, 'VOD_LPDR2_%s_%03d_%s_clip_map_copy.tif'%(year,date,pass_type),\
                                        pixel_type='16_BIT_UNSIGNED',nodata_value='0')
            ##make raster table
            inRaster = 'VOD_LPDR2_%s_%03d_%s_clip_map_copy.tif' % (year, date,
                                                                   pass_type)
            arcpy.BuildRasterAttributeTable_management(inRaster, "Overwrite")
arcpy.CheckInExtension("Spatial")
end_time = time.clock()
time_taken = end_time - start_time
print('Program executed in %s seconds' % time_taken)
Exemple #7
0
def function(outputFolder,
             preprocessFolder,
             lsOption,
             slopeAngle,
             soilOption,
             soilData,
             soilCode,
             lcOption,
             landCoverData,
             landCoverCode,
             rData,
             saveFactors,
             supportData,
             rerun=False):

    try:
        # Set temporary variables
        prefix = os.path.join(arcpy.env.scratchGDB, "rusle_")

        supportCopy = prefix + "supportCopy"
        soilResample = prefix + "soilResample"
        lcResample = prefix + "lcResample"
        rainResample = prefix + "rainResample"
        supportResample = prefix + "supportResample"
        soilClip = prefix + "soilClip"
        landCoverClip = prefix + "landCoverClip"
        rainClip = prefix + "rainClip"
        supportClip = prefix + "supportClip"
        DEMSlopeCut = prefix + "DEMSlopeCut"
        DEMSlopeRad = prefix + "DEMSlopeRad"
        upslopeArea = prefix + "upslopeArea"
        soilJoin = prefix + "soilJoin"
        lcJoin = prefix + "lcJoin"
        rFactor = prefix + "rFactor"
        lsFactor = prefix + "lsFactor"
        kFactor = prefix + "kFactor"
        cFactor = prefix + "cFactor"
        pFactor = prefix + "pFactor"
        soilLossInt = prefix + "soilLossInt"
        landCoverRas = prefix + "landCoverRas"
        soilRas = prefix + "soilRas"
        dataMask = prefix + "dataMask"

        # Get input study area mask
        files = common.getFilenames('preprocess', preprocessFolder)
        studyMask = files.studyareamask
        inputLC = files.lc_ras
        inputSoil = files.soil_ras
        DEMSlopePerc = files.slopeRawPer
        DEMSlope = files.slopeHydDeg
        hydFAC = files.hydFAC
        rawDEM = files.rawDEM
        streamInvRas = files.streamInvRas

        # Set output filenames
        files = common.getFilenames('rusle', outputFolder)
        soilLoss = files.soilloss

        if saveFactors:
            # if RUSLE factor layers are to be saved

            rFactor = files.rFactor
            lsFactor = files.lsFactor
            kFactor = files.kFactor
            cFactor = files.cFactor
            pFactor = files.pFactor

        reconOpt = common.getInputValue(preprocessFolder, 'Recondition_DEM')

        ####################
        ### Check inputs ###
        ####################

        codeBlock = 'Check if new inputs are in a projected coordinate systems'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            inputs = [rData]

            optInputs = [soilData, landCoverData, supportData]
            for data in optInputs:
                if data is not None:
                    inputs.append(data)

            for data in inputs:
                spatialRef = arcpy.Describe(data).spatialReference

                if spatialRef.Type == "Geographic":
                    # If any of the inputs are not in a projected coordinate system, the tool exits with a warning
                    log.error('Data: ' + str(data))
                    log.error(
                        'This data has a Geographic Coordinate System. It must have a Projected Coordinate System.'
                    )
                    sys.exit()

            log.info(
                'All new inputs are in a projected coordinate system, proceeding.'
            )

            progress.logProgress(codeBlock, outputFolder)

        try:

            # Set environment and extents to DEM
            RawDEM = Raster(rawDEM)

            arcpy.env.extent = RawDEM
            arcpy.env.mask = RawDEM
            arcpy.env.cellSize = RawDEM
            arcpy.env.compression = "None"

            cellsizedem = float(
                arcpy.GetRasterProperties_management(rawDEM,
                                                     "CELLSIZEX").getOutput(0))

            log.info("Calculation extent set to DEM data extent")

        except Exception:
            log.error("Environment and extent conditions not set correctly")
            raise

        codeBlock = 'Convert any vector inputs to raster'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            if landCoverData is not None:
                lcFormat = arcpy.Describe(landCoverData).dataType

                if lcFormat in ['ShapeFile', 'FeatureClass']:

                    arcpy.PolygonToRaster_conversion(landCoverData,
                                                     landCoverCode,
                                                     landCoverRas,
                                                     "CELL_CENTER", "",
                                                     cellsizedem)
                    log.info('Land cover raster produced')

                else:
                    arcpy.CopyRaster_management(landCoverData, landCoverRas)

            if soilData is not None:
                soilFormat = arcpy.Describe(soilData).dataType

                if soilFormat in ['ShapeFile', 'FeatureClass']:

                    arcpy.PolygonToRaster_conversion(soilData, soilCode,
                                                     soilRas, "CELL_CENTER",
                                                     "", cellsizedem)
                    log.info('Soil raster produced')

                else:
                    arcpy.CopyRaster_management(soilData, soilRas)

            progress.logProgress(codeBlock, outputFolder)

        codeBlock = 'Resample down to DEM cell size'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            # Resample down to DEM cell size
            log.info("Resampling inputs down to DEM cell size")

            resampledRainTemp = arcpy.sa.ApplyEnvironment(rData)
            resampledRainTemp.save(rainResample)
            del resampledRainTemp

            if soilData is not None:
                resampledSoilTemp = arcpy.sa.ApplyEnvironment(soilRas)
                resampledSoilTemp.save(soilResample)
                del resampledSoilTemp

                # Delete soil raster
                arcpy.Delete_management(soilRas)

            if landCoverData is not None:
                resampledLCTemp = arcpy.sa.ApplyEnvironment(landCoverRas)
                resampledLCTemp.save(lcResample)
                del resampledLCTemp

                # Delete land cover raster
                arcpy.Delete_management(landCoverRas)

            if supportData is not None:

                arcpy.CopyRaster_management(supportData, supportCopy)
                resampledPTemp = arcpy.sa.ApplyEnvironment(supportCopy)
                resampledPTemp.save(supportResample)
                del resampledPTemp

                # Delete support raster
                arcpy.Delete_management(supportCopy)

            log.info("Inputs resampled")

            progress.logProgress(codeBlock, outputFolder)

        codeBlock = 'Clip inputs'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            log.info("Clipping inputs")

            arcpy.Clip_management(rainResample,
                                  "#",
                                  rainClip,
                                  studyMask,
                                  clipping_geometry="ClippingGeometry")

            # Delete resampled R-factor
            arcpy.Delete_management(rainResample)

            if soilData is not None:
                arcpy.Clip_management(soilResample,
                                      "#",
                                      soilClip,
                                      studyMask,
                                      clipping_geometry="ClippingGeometry")

                # Delete resampled soil
                arcpy.Delete_management(soilResample)

            if landCoverData is not None:
                arcpy.Clip_management(lcResample,
                                      "#",
                                      landCoverClip,
                                      studyMask,
                                      clipping_geometry="ClippingGeometry")

                # Delete resampled land cover
                arcpy.Delete_management(lcResample)

            if supportData is not None:
                arcpy.Clip_management(supportResample,
                                      "#",
                                      supportClip,
                                      studyMask,
                                      clipping_geometry="ClippingGeometry")

                # Delete resampled support data
                arcpy.Delete_management(supportResample)

            log.info("Inputs clipped")

            progress.logProgress(codeBlock, outputFolder)

        codeBlock = 'Check against study area mask'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            inputs = [rainClip]

            optInputs = [soilClip, landCoverClip, supportClip]
            for data in optInputs:
                if arcpy.Exists(data):
                    inputs.append(data)

            for data in inputs:
                dataMask = common.extractRasterMask(data)
                common.checkCoverage(dataMask, studyMask, data)
                del dataMask

            progress.logProgress(codeBlock, outputFolder)

        ####################################
        ### Rainfall factor calculations ###
        ####################################

        codeBlock = 'Produce R-factor layer'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            # Copy resampled raster
            arcpy.CopyRaster_management(rainClip, rFactor)

            # Delete clipped R-factor
            arcpy.Delete_management(rainClip)

            log.info("R-factor layer produced")

            progress.logProgress(codeBlock, outputFolder)

        ######################################################
        ### Slope length and steepness factor calculations ###
        ######################################################

        codeBlock = 'Produce LS-factor layer'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            # Calculate the threshold slope angle in percent
            lsFactorRad = float(slopeAngle) * (math.pi / 180.0)
            riseRun = math.tan(lsFactorRad)
            cutoffPercent = riseRun * 100.0

            if lsOption == 'SlopeLength':

                log.info(
                    "Calculating LS-factor based on slope length and steepness only"
                )

                # Produce slope cutoff raster
                DEMSlopeCutTemp = Con(
                    Raster(DEMSlopePerc) > float(cutoffPercent),
                    float(cutoffPercent), Raster(DEMSlopePerc))
                DEMSlopeCutTemp.save(DEMSlopeCut)
                del DEMSlopeCutTemp

                # Calculate the parts of the LS-factor equation separately
                lsCalcA = (cellsizedem / 22.0)**0.5
                lsCalcB = 0.065 + (0.045 * Raster(DEMSlopeCut)) + (
                    0.0065 * Power(Raster(DEMSlopeCut), 2.0))

                # Calculate the LS-factor
                lsOrigTemp = lsCalcA * lsCalcB
                lsOrigTemp.save(lsFactor)

                # Delete temporary files
                del lsCalcB
                del lsOrigTemp
                arcpy.Delete_management(DEMSlopeCut)

                log.info("LS-factor layer produced")

            elif lsOption == 'UpslopeArea':

                if reconOpt == 'false':
                    log.error(
                        'Cannot calculate LS-factor including upslope contributing area on unreconditioned DEM'
                    )
                    log.error(
                        'Rerun the preprocessing tool to recondition the DEM')
                    sys.exit()

                log.info(
                    "Calculating LS-factor including upslope contributing area"
                )

                # Produce slope cutoff raster
                DEMSlopeCutTemp = Con(
                    Raster(DEMSlope) > float(slopeAngle), float(slopeAngle),
                    Raster(DEMSlope))
                DEMSlopeCutTemp.save(DEMSlopeCut)
                del DEMSlopeCutTemp

                # Convert from degrees to radian
                DEMSlopeRadTemp = Raster(DEMSlopeCut) * 0.01745
                DEMSlopeRadTemp.save(DEMSlopeRad)
                del DEMSlopeRadTemp

                # Currently hardcoded, but should have them as options in future
                m = 0.5
                n = 1.2

                upslopeAreaTemp = Raster(hydFAC) * float(cellsizedem)
                upslopeAreaTemp.save(upslopeArea)
                del upslopeAreaTemp

                lsFactorTemp = (m + 1) * Power(
                    Raster(upslopeArea) / 22.1, float(m)) * Power(
                        Sin(Raster(DEMSlopeRad)) / 0.09, float(n))
                lsFactorTemp.save(lsFactor)
                del lsFactorTemp

                # Delete temporary files
                arcpy.Delete_management(DEMSlopeCut)
                arcpy.Delete_management(DEMSlopeRad)
                arcpy.Delete_management(upslopeArea)

                log.info("LS-factor layer produced")

            progress.logProgress(codeBlock, outputFolder)

        ################################
        ### Soil factor calculations ###
        ################################

        codeBlock = 'Produce K-factor layer'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            if soilOption == 'PreprocessSoil':

                # Use the soil from the preprocessFolder
                arcpy.CopyRaster_management(inputSoil, soilClip)

                kTable = os.path.join(configuration.tablesPath,
                                      "rusle_hwsd.dbf")
                arcpy.JoinField_management(soilClip, "VALUE", kTable,
                                           "MU_GLOBAL")
                arcpy.CopyRaster_management(soilClip, soilJoin)

                # Delete temporary files
                arcpy.Delete_management(soilClip)

                kOrigTemp = Lookup(soilJoin, "K_Stewart")
                kOrigTemp.save(kFactor)

                # Delete temporary files
                del kOrigTemp
                arcpy.Delete_management(soilJoin)

            elif soilOption == 'LocalSoil':

                # User input is their own K-factor dataset
                kOrigTemp = Raster(soilClip)
                kOrigTemp.save(kFactor)

                # Delete temporary files
                del kOrigTemp
                arcpy.Delete_management(soilClip)

            else:
                log.error('Invalid soil erodibility option')
                sys.exit()

            log.info("K-factor layer produced")

            progress.logProgress(codeBlock, outputFolder)

        #################################
        ### Cover factor calculations ###
        #################################

        codeBlock = 'Produce C-factor layer'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            if lcOption == 'PrerocessLC':

                # Use LC from the preprocess folder

                arcpy.CopyRaster_management(inputLC, landCoverClip)

                cTable = os.path.join(configuration.tablesPath,
                                      "rusle_esacci.dbf")

                arcpy.JoinField_management(landCoverClip, "VALUE", cTable,
                                           "LC_CODE")
                arcpy.CopyRaster_management(landCoverClip, lcJoin)

                arcpy.Delete_management(landCoverClip)

                cOrigTemp = Lookup(lcJoin, "CFACTOR")
                cOrigTemp.save(cFactor)

                # Delete temporary files
                del cOrigTemp
                arcpy.Delete_management(lcJoin)

            elif lcOption == 'LocalCfactor':

                # User input is their own C-factor dataset

                cOrigTemp = Raster(landCoverClip)
                cOrigTemp.save(cFactor)

                # Delete temporary files
                del cOrigTemp
                arcpy.Delete_management(landCoverClip)

            else:
                log.error('Invalid C-factor option')
                sys.exit()

            log.info("C-factor layer produced")

            progress.logProgress(codeBlock, outputFolder)

        #####################################
        ### Support practice calculations ###
        #####################################

        codeBlock = 'Produce P-factor layer'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            if supportData is not None:
                arcpy.CopyRaster_management(supportClip, pFactor)
                log.info("P-factor layer produced")

                # Delete temporary files
                arcpy.Delete_management(supportClip)

            progress.logProgress(codeBlock, outputFolder)

        ##############################
        ### Soil loss calculations ###
        ##############################

        codeBlock = 'Produce soil loss layer'
        if not progress.codeSuccessfullyRun(codeBlock, outputFolder, rerun):

            if supportData is not None:
                soilLossTemp = Raster(rFactor) * Raster(lsFactor) * Raster(
                    kFactor) * Raster(cFactor) * Raster(pFactor)

            else:
                soilLossTemp = Raster(rFactor) * Raster(lsFactor) * Raster(
                    kFactor) * Raster(cFactor)

            if lsOption == 'UpslopeArea':
                soilLossTemp = soilLossTemp * Raster(streamInvRas)
                soilLossTemp.save(soilLoss)

            else:
                soilLossTemp.save(soilLoss)

            log.info("RUSLE function completed successfully")

            progress.logProgress(codeBlock, outputFolder)

        return soilLoss

    except Exception:
        arcpy.AddError("RUSLE function failed")
        raise

    finally:
        # Remove feature layers from memory
        try:
            for lyr in common.listFeatureLayers(locals()):
                arcpy.Delete_management(locals()[lyr])
                exec(lyr + ' = None') in locals()
        except Exception:
            pass