def cc_copy_inputs(): """Clip Climate Linkage Mapper inputs to smallest extent""" lm_util.gprint("\nCOPYING LAYERS AND, IF NECESSARY, REDUCING EXTENT") ext_poly = "ext_poly" # Extent polygon climate_extent = arcpy.Raster(cc_env.climate_rast).extent if cc_env.resist_rast is not None: resist_extent = arcpy.Raster(cc_env.resist_rast).extent xmin = max(climate_extent.XMin, resist_extent.XMin) ymin = max(climate_extent.YMin, resist_extent.YMin) xmax = min(climate_extent.XMax, resist_extent.XMax) ymax = min(climate_extent.YMax, resist_extent.YMax) # Set to minimum extent if resistance raster was given arcpy.env.extent = arcpy.Extent(xmin, ymin, xmax, ymax) # Want climate and resistance rasters in same spatial ref # with same nodata cells proj_resist_rast = sa.Con(sa.IsNull(cc_env.climate_rast), sa.Int(cc_env.climate_rast), cc_env.resist_rast) proj_resist_rast.save(cc_env.prj_resist_rast) else: xmin = climate_extent.XMin ymin = climate_extent.YMin xmax = climate_extent.XMax ymax = climate_extent.YMax ones_resist_rast = sa.Con(sa.IsNull(cc_env.climate_rast), sa.Int(cc_env.climate_rast), 1) ones_resist_rast.save(cc_env.prj_resist_rast) arcpy.CopyRaster_management(cc_env.climate_rast, cc_env.prj_climate_rast) # Create core raster arcpy.env.extent = arcpy.Extent(xmin, ymin, xmax, ymax) lm_util.delete_data(cc_env.prj_core_rast) arcpy.FeatureToRaster_conversion( cc_env.core_fc, cc_env.core_fld, cc_env.prj_core_rast, arcpy.Describe(cc_env.climate_rast).MeanCellHeight) arcpy.env.extent = None # Create array of boundary points array = arcpy.Array() pnt = arcpy.Point(xmin, ymin) array.add(pnt) pnt = arcpy.Point(xmax, ymin) array.add(pnt) pnt = arcpy.Point(xmax, ymax) array.add(pnt) pnt = arcpy.Point(xmin, ymax) array.add(pnt) # Add in the first point of the array again to close polygon boundary array.add(array.getObject(0)) # Create a polygon geometry object using the array object ext_feat = arcpy.Polygon(array) arcpy.CopyFeatures_management(ext_feat, ext_poly) # Clip core feature class arcpy.Clip_analysis(cc_env.core_fc, ext_poly, cc_env.prj_core_fc)
patchIDs.append(row.VALUE) row = rows.next() del row, rows # Loop through patches and and calculate least cost paths streamFC = "in_memory/LCPlines" first = True for patchID in patchIDs: msg("Working on patch %s of %s" % (patchID, len(patchIDs))) # Idenfity the cost and back link rasters cdRaster = os.path.join(CostDistWS, "CD_%s.img" % patchID) blRaster = os.path.join(CostDistWS, "BL_%s.img" % patchID) # Calculate least cost paths from all patches to the current patch lcpRaster = sa.CostPath(patchFix, cdRaster, blRaster, "EACH_ZONE") if first: lcpOutput = sa.Con(sa.IsNull(lcpRaster), 0, 1) first = False else: lcpTemp = sa.Con(sa.IsNull(lcpRaster), 0, 1) + lcpOutput lcpOutput = sa.Con(lcpTemp, 1, 0, "VALUE > 0") ''' # Convert the backlink to a flow direction raster #fdRaster = sa.Int(sa.Exp2(blRaster) / 2) # Convert the LCP raster to a vector if first: # If the first patch, save the streamsFC to the output FC file sa.StreamToFeature(lcpRaster,fdRaster,lcpFC,"NO_SIMPLIFY") first = False else: # Otherwise, create it and append it to the original sa.StreamToFeature(lcpRaster,fdRaster,streamFC,"NO_SIMPLIFY") arcpy.Append_management(streamFC,lcpFC) '''
# f3: vegetation f3t = os.path.join(scratch,"f3t") f3 = os.path.join(scratch,"f3") arcpy.AddMessage("Clipping vegetation to fishnet and joining parameter table...") vegetation = os.path.join("in_memory","vegetation") if debug == True: arcpy.AddMessage(str(time.strftime("Clip Vegetation: %m/%d/%Y %H:%M:%S", time.localtime()))) arcpy.Clip_analysis(inputVegetation,inputAOI,vegetation) deleteme.append(vegetation) arcpy.JoinField_management(vegetation,"f_code",inputVegetationConversionTable,"f_code") # Convert vegetation to Raster using MIN or MAX field if min_max == "MAX": arcpy.PolygonToRaster_conversion(vegetation,"f3max",f3t) else: arcpy.PolygonToRaster_conversion(vegetation,"f3min",f3t) # if F3T is null, make it 1.0 (from constNoEffect), otherwise keep F3T value outF3T = sa.Con(sa.IsNull(f3t),constNoEffect,f3t) outF3T.save(f3) deleteme.append(f3t) deleteme.append(f3) #TODO: what about areas in the AOI but outside VEG? No effect (value = 1.0)? ccmFactorList.append(f3) if inputSoils != types.NoneType and arcpy.Exists(inputSoils) == True: # f4: soils f4t = os.path.join(scratch,"f4t") f4 = os.path.join(scratch,"f4") arcpy.AddMessage("Clipping soils to fishnet and joining parameter table...") clipSoils = os.path.join("in_memory","clipSoils") if debug == True: arcpy.AddMessage(str(time.strftime("Clip Soils: %m/%d/%Y %H:%M:%S", time.localtime()))) arcpy.Clip_analysis(inputSoils,inputAOI,clipSoils) deleteme.append(clipSoils)
def preprocess(layerName): """ Source dir: resistances Output dir: preprocessed """ paths.setEnv(env) env.overwriteOutput = True source = paths.join(paths.resistances, layerName) output = paths.join(paths.preprocessed, layerName) print "Preprocessing {}: {} ==> {}".format(layerName, source, output) if arcpy.Exists(output) and not redoExistingOutput: print "{} already exists, leaving it as is.".format(output) return output for tempras in ["projected", "clipped"]: try: arcpy.Raster(tempras) print "Deleting temporary: {}".format(tempras) arcpy.Delete_management(tempras) except RuntimeError: pass # tempfile doesn't exist, we're good print "Projecting and resampling..." arcpy.ProjectRaster_management(source, "projected", paths.alaskaAlbers, cell_size=500) source = arcpy.Raster(source) print "Initial extent: {} {} {} {}".format(source.extent.XMin, source.extent.YMin, source.extent.XMax, source.extent.YMax) newExt = arcpy.Describe(paths.studyArea).extent print "New intended extent: {} {} {} {}".format(newExt.XMin, newExt.YMin, newExt.XMax, newExt.YMax) print "Clipping..." # TODO: despite specifying an extent, it refuses to clip to exactly that (except by filling in borders with NoData) arcpy.Clip_management("projected", "", "clipped", paths.studyArea, "", "ClippingGeometry", "NO_MAINTAIN_EXTENT") clipped = arcpy.Raster("clipped") print "New actual extent: {} {} {} {}".format(clipped.extent.XMin, clipped.extent.YMin, clipped.extent.XMax, clipped.extent.YMax) print "Normalizing..." outRas = arcpy.Raster("clipped") outRas = (outRas - outRas.minimum) / (outRas.maximum - outRas.minimum) # de-null outRas = sa.Con(sa.IsNull(outRas), 0, outRas) env.overwriteOutput = True outRas.save(output) arcpy.Delete_management("projected") arcpy.Delete_management("clipped") return output
dict = {} dict[1] = 3 #D dict[2] = 2 #C dict[3] = 1 #V dict[4] = 2 #C/D dict[5] = 0 #A dict[6] = 1 #B/D dict[7] = 0 #A/D return dict cnDict = createCNDict() hgrpDict = createHgrpLookup() # Plug NoData values in hgrpRasters with a class of D hgrpFix = sa.Con(sa.IsNull(hgrpRaster), 1, hgrpRaster) # combine the rasters msg("Combining NLCD and Hydrologic group rasters") comboRaster = sa.Combine([nlcdRaster, hgrpFix]) nlcdFld = arcpy.ListFields(comboRaster)[-2].name hgrpFld = arcpy.ListFields(comboRaster)[-1].name # add a new field to the comboRaster msg("Adding curve number field to output raster") arcpy.AddField_management(comboRaster, "CN", "LONG", 4) # update values based on the dictionary msg("Adding curve number values to output raster") rows = arcpy.UpdateCursor(comboRaster) row = rows.next()
# ---Functions--- def msg(txt, type="message"): print txt if type == "message": arcpy.AddMessage(txt) elif type == "warning": arcpy.AddWarning(txt) elif type == "error": arcpy.AddError(txt) # ---Processes--- ## Create a raster of stream cells, with values set to elevation msg("Creating a streams raster (inverting NHD FlowDirNull Raster)") strmRaster = sa.IsNull(fdrnullRaster) msg("Assigning elevation values to stream cells") strmElevRaster1 = sa.Con(strmRaster, elevRaster) #If the elevation values strmElevRaster = sa.Con(strmElevRaster1, strmElevRaster1, 1, "VALUE >= 1") ## Create a watershed, using the stream elevation raster as the pour points. '''Cell values in this output are the elevation at the point where the given cell's location flows into the stream. This, in turn, can be compared to the actual elevation at the cell's location to compute the vertical drop between the cell and where it drains into the stream''' msg("Calculating watersheds labeled with elevation") try: elevSheds = sa.Watershed(fldrRaster, strmElevRaster, "VALUE") except:
#Output variables dist2edgeRaster = sys.argv[ 6] #r'C:\WorkSpace\GBAT2012\GHAT_V011\scratch\dist2edge' corePatches = sys.argv[ 7] #r'C:\WorkSpace\GBAT2012\GHAT_V011\scratch\corePatches' dist2habRaster = sys.argv[ 8] #r'C:\WorkSpace\GBAT2012\GHAT_V011\scratch\dist2hab' subnetRaster = sys.argv[9] #r'C:\WorkSpace\GBAT2012\GHAT_V011\scratch\subnet' dist2protRaster = sys.argv[ 10] #r'C:\WorkSpace\GBAT2012\GHAT_V011\scratch\dist2prot' ##--Process 1: Calculate distance to patch edge-- arcpy.AddMessage("Calculating distance to patch edge") arcpy.AddMessage("...inverting habitat raster") nonHabitatBinary = sa.Con(sa.IsNull(patchRaster), 1) arcpy.AddMessage("...calculating distances from edge into patch") eucDist = sa.EucDistance(nonHabitatBinary) eucDist.save(dist2edgeRaster) ##--Process 2: Extract core areas (using distance to edge) arcpy.AddMessage("Extracting core areas") core = sa.SetNull(eucDist, patchRaster, "VALUE <= %s" % edgeWidth) core.save(corePatches) ##--Process 3: Calculate cost distance away from patch arcpy.AddMessage("Calculating cost distance from patches") costDist2H = sa.CostDistance(patchRaster, costRaster) costDist2H.save(dist2habRaster) ##-Process 4: Extract patch subnetwork areas (from distance to habitat)
# Message function def msg(txt): print txt; arcpy.AddMessage(txt); return ##-PROCESSES- # 1. Convert curve number to a weight: Int((100 - cn) / 10). Higher CN values # reflect increased runoff across the cell. This equation inverts the # CN value and scales it to values from 0 to 10. The resulting value reflects # a proxy for infiltration: higher values suggest more runoff stays in the cell # meaning less pollutants will leave the cell to downstream neighbors. msg("Calculating flow length weight from %s" %cnRaster) weightRaster = sa.Int(sa.Divide(sa.Minus(100.0,cnRaster), 10.0) + 1) # 2. Create a flow direction where streams are NoData. This enables calculation # of flow length to the stream vs to the stream outlet. msg("Creating modified flow direction to calculate distance to streams") fdRaster = sa.Con(sa.IsNull(streamsRaster),flowdirRaster) # 3. Calculate cost-weighted flowlength. Cell values represent the infiltrated- # weighted distance along the flow path to a stream. Two paths may be the same # length, but if one goes through cells with high curve numbers (low weights) # it's path will be effectively shorter whereas a path going through cells with # low curve numbers (high weights) will be effectively longer - in terms of # suspended/dissolved pollutants reaching the stream. msg("Calculating weighted flow length") wtdflRaster1 = sa.FlowLength(fdRaster,"DOWNSTREAM",weightRaster) + 30 #Set stream pixels to 0 wtdflRaster = sa.Con(sa.IsNull(streamsRaster), wtdflRaster1, 0) # 4. Apply a decay coefficient to weighted flow lengths to create distance decay raster # k = math.log(0.01) / d, where d is obtained from the unweighted flow length(?) msg("Calculating distance decayed rasters")