def run_analysis(): """Run Climate Linkage Mapper analysis.""" import cc_grass_cwd # Cannot import until configured cc_copy_inputs() # Clip inputs and create project area raster # Get zonal statistics for cores and climate lm_util.gprint("\nCALCULATING ZONAL STATISTICS FROM CLIMATE RASTER") climate_stats = arcpy.sa.ZonalStatisticsAsTable(cc_env.prj_core_fc, cc_env.core_fld, cc_env.prj_climate_rast, "zstats", "DATA", "ALL") # Create core pairings table and limit based upon climate threshold core_pairings = create_pair_tbl(climate_stats) # Generate link table, calculate CWD and run Linkage Mapper if int(arcpy.GetCount_management(core_pairings).getOutput(0)) == 0: lm_util.warn("\nNo core pairs within climate threshold. " "Program will end") else: # Process pairings and generate link table grass_cores = process_pairings(core_pairings) if not grass_cores: lm_util.warn("\nNo core pairs within Euclidean distances. " "Progam will end") else: # Create CWD using Grass cc_grass_cwd.grass_cwd(grass_cores) # Run Linkage Mapper lm_util.gprint("\nRUNNING LINKAGE MAPPER " "TO CREATE CLIMATE CORRIDORS") lm_master.lm_master()
def run_analysis(): """Run Climate Linkage Mapper analysis""" import cc_grass_cwd # Cannot import until configured zonal_tbl = "zstats.dbf" cc_copy_inputs() # Clip inputs and create project area raster # Get zonal statistics for cores and climate lm_util.gprint("\nCALCULATING ZONAL STATISTICS FROM CLIMATE RASTER") climate_stats = arcpy.sa.ZonalStatisticsAsTable( cc_env.prj_core_fc, cc_env.core_fld, cc_env.prj_climate_rast, zonal_tbl, "DATA", "ALL") # Create core pairings table and limit based upon climate threshold core_pairings = create_pair_tbl(climate_stats) # Generate link table, calculate CWD and run Linkage Mapper if int(arcpy.GetCount_management(core_pairings).getOutput(0)) == 0: arcpy.AddWarning("\nNo core pairs within climate threshold. " "Program will end") else: # Process pairings and generate link table grass_cores = process_pairings(core_pairings) if not grass_cores: arcpy.AddWarning("\nNo core pairs within Euclidean distances. " "Progam program will end") else: # Create CWD using Grass cc_grass_cwd.grass_cwd(grass_cores) # Run Linkage Mapper lm_util.gprint("\nRUNNING LINKAGE MAPPER " "TO CREATE CLIMATE CORRIDORS") lm_master.lm_master()
def main(): """Set path and run model.""" demo_path = (os.path.abspath( os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))) sys.path.append(os.path.join(demo_path, '..\\toolbox\\scripts')) import lm_master lm_master.lm_master(in_params(demo_path))
def main(): """Runs Linkage Mapper with coded inputs""" proj_dir = "V:\\demoProject" core_fc = "V:\\demoData\\Cores.shp" core_fl = "core_ID" resis_rast = "V:\\demoData\\resistances" # distance_file = "V:\\demoData\\distances_Cores.txt" arg = (_SCRIPT_NAME, proj_dir, core_fc, core_fl, resis_rast, "true", "true", "Cost-Weighted & Euclidean", "#", "true", "true", "false", "4", "Cost-Weighted", "false", "true", "100000", "100000", "100000") sys.argv = arg sys.path.append('../toolbox/scripts') import lm_master lm_master.lm_master()
def main(argv=None): """Iterate over LM, BM, and restoration tasks.""" if argv is None: argv = sys.argv # Get parameters from ArcGIS tool dialog start_time = time.clock() # USER SETTINGS ###################################################### # Restoration Settings # ALL input data must be in the same projection # Set to True to restore highest ROI. Set to False to restore strongest # barrier restore_max_roi = argv[1] # Resistance value of restored habitat. Must be 1 or greater. restored_resistance_val = argv[2] # No spaces or special chars in paths or gdb names restoration_data_gdb = argv[3] # No spaces in path, avoid using dropbox or network drive # Project directories will be created in this (iter1, iter2...) as will an # output geodatabase output_dir = argv[4] # Resistance raster. Should be in input GDB resistance_ras = argv[5] # Core area feature class. Should be in input GDB 'URWA_HCAs_Doug_Grant' core_fc = argv[6] core_fn = argv[7] # Core area field name radius = argv[8] # Restoration radius in meters iterations = argv[9] # Number of restorations to perform # If less than this proportion of ag in circle, don't consider restoring # circle min_ag_threshold = argv[10] # Don't consider barriers below this improvement score (average improvement # per meter diameter restored) min_improvement_val = argv[11] # Average per-m2 parcel cost per pixel. Snapped to resistance raster. parcel_cost_ras = argv[12] # Right now this is just a raster with all pixels set to 0.113174 restoration_cost_ras = argv[13] ag_ras = argv[14] # 1=Ag, 0=Not Ag # Some restorations benefit multiple corridors. # 'Maximum' takes the greatest improvement across core area pairs # 'Sum' adds improvement scores acreoss all pairs. barrier_combine_method = argv[15] # Use cwd_thresh = None for no threshold. Use cwd_thresh = X to not # consider restorations more than X map units away from each core area. cwd_thresh = argv[16] # END USER SETTINGS ###################################################### try: # Setup path and create directories gprint('Hey! Make sure everything is in the same projection!\n') gprint('Setting up paths and creating directories') sys.path.append('..\\toolbox\\scripts') res_ras = os.path.join(restoration_data_gdb, resistance_ras) core_fc_path = os.path.join(restoration_data_gdb, core_fc) # Set up a NEW output gdb (leave previous ones on drive) i = None for i in range(1, 200): output_gdb = 'restorationOutput' + str(i) + '.gdb' if not arcpy.Exists(os.path.join(output_dir, output_gdb)): break gprint('Previous output GDB ' + output_gdb + ' exists. ' 'Delete to save disk space.') arcpy.CreateFileGDB_management(output_dir, output_gdb) output_gdb = os.path.join(output_dir, output_gdb) log_file = os.path.join(output_gdb, 'Iterate Barriers' + str(i) + '.py') # Write a copy of this file to output dir as a record of settings shutil.copyfile(__file__, log_file) arcpy.env.cellSize = res_ras arcpy.env.extent = res_ras arcpy.env.snapRaster = res_ras arcpy.env.overwriteOutput = True arcpy.env.scratchWorkspace = output_gdb arcpy.env.workspace = output_gdb spatialref = arcpy.Describe(res_ras).spatialReference mapunits = spatialref.linearUnitName gprint('Cell size = ' + str(arcpy.env.cellSize) + ' ' + mapunits + 's') # Calculate fraction of ag within radius of each pixel gprint('Calculating purchase cost, fraction of ag, etc within radius ' 'of each pixel.') ag_ras = os.path.join(restoration_data_gdb, ag_ras) in_neighborhood = arcpy.sa.NbrCircle(radius, "MAP") arcpy.env.extent = ag_ras out_focal_stats = arcpy.sa.FocalStatistics(ag_ras, in_neighborhood, "MEAN", "NODATA") proportion_ag_ras = os.path.join(output_gdb, 'proportionAgRas') out_focal_stats.save(proportion_ag_ras) arcpy.env.extent = res_ras # Calculate purchase cost of circles parcel_cost_ras = os.path.join(restoration_data_gdb, parcel_cost_ras) arcpy.env.extent = parcel_cost_ras out_focal_stats = arcpy.sa.FocalStatistics(parcel_cost_ras, in_neighborhood, "MEAN", "DATA") cost_focal_stats_ras = os.path.join(output_gdb, 'cost_focal_stats_ras') out_focal_stats.save(cost_focal_stats_ras) arcpy.env.extent = res_ras circle_area = float(npy.pi * radius * radius) outras = arcpy.sa.Raster(cost_focal_stats_ras) * circle_area purch_cost_ras = os.path.join(output_gdb, 'purchaseCostRaster') outras.save(purch_cost_ras) lu.delete_data(cost_focal_stats_ras) restoration_cost_ras = os.path.join(restoration_data_gdb, restoration_cost_ras) outras = ( arcpy.sa.Raster(purch_cost_ras) + (arcpy.sa.Raster(restoration_cost_ras) * radius * radius * npy.pi)) total_cost_ras = os.path.join(output_gdb, 'totalCostRaster') outras.save(total_cost_ras) # Create mask to remove areas without cost data arcpy.env.extent = total_cost_ras cost_mask_ras = os.path.join(output_gdb, 'costMaskRaster') cost_thresh = 0 out_con = arcpy.sa.Con( (arcpy.sa.Raster(total_cost_ras) > float(cost_thresh)), 1) out_con.save(cost_mask_ras) arcpy.env.extent = res_ras # Create mask to remove areas below ag threshold out_con = arcpy.sa.Con( (arcpy.sa.Raster(proportion_ag_ras) > float(min_ag_threshold)), 1) ag_mask_ras = os.path.join(output_gdb, 'agMaskRaster') out_con.save(ag_mask_ras) do_step_1 = 'true' do_step_2 = 'true' do_step_5 = 'false' all_restored_areas_ras = '' for cur_iter in range(1, iterations + 1): start_time1 = time.clock() # Some env settings get changed by linkage mapper and must be # reset here arcpy.env.cellSize = res_ras arcpy.env.extent = res_ras arcpy.env.snapRaster = res_ras arcpy.env.scratchWorkspace = output_gdb arcpy.env.workspace = output_gdb lu.dashline(1) gprint('Running iteration number ' + str(cur_iter)) proj_dir = os.path.join(output_dir, 'iter' + str(cur_iter) + 'Proj') lu.create_dir(output_dir) lu.delete_dir(proj_dir) lu.create_dir(proj_dir) if cur_iter > 1: # Copy previous s2 linktable to new project dir datapass_dir = os.path.join(proj_dir, 'datapass') lu.create_dir(datapass_dir) proj_dir1 = os.path.join(output_dir, 'iter1Proj') datapass_dir_iter1 = os.path.join(proj_dir1, 'datapass') s2_link_tbl_iter1 = os.path.join(datapass_dir_iter1, 'linkTable_s2.csv') s2_link_tbl = os.path.join(datapass_dir, 'linkTable_s2.csv') shutil.copyfile(s2_link_tbl_iter1, s2_link_tbl) # Run Linkage Mapper # Copy distances text file from earlier LM run to the output # directory- speeds things up! dist_file = os.path.join(output_dir, core_fc + '_dists.txt') if not os.path.exists(dist_file): if cur_iter == 1: gprint('Will calculate distance file.') dist_file = '#' else: proj_dir1 = os.path.join(output_dir, 'iter1Proj') dist_file1 = os.path.join(proj_dir1, core_fc + '_dists.txt') # Put a copy here for future runs shutil.copyfile(dist_file1, dist_file) arcpy.env.scratchWorkspace = output_gdb arcpy.env.workspace = output_gdb argv = ('lm_master.py', proj_dir, core_fc_path, core_fn, res_ras, do_step_1, do_step_2, 'Cost-Weighted & Euclidean', dist_file, 'true', 'true', 'false', '4', 'Cost-Weighted', 'true', do_step_5, 'true', '200000', '10000', '#', '#', '#', '#') gprint('Running ' + str(argv)) lm_master.lm_master(argv) do_step_1 = 'false' # Can skip for future iterations do_step_2 = 'false' # Can skip for future iterations do_step_5 = 'false' # Skipping for future iterations start_radius = str(radius) end_radius = str(radius) radius_step = '0' save_radius_ras = 'false' write_pct_ras = 'false' argv = ('barrier_master.py', proj_dir, res_ras, start_radius, end_radius, radius_step, barrier_combine_method, save_radius_ras, write_pct_ras, cwd_thresh) gprint('Running ' + str(argv)) barrier_master.bar_master(argv) # Some env settings get changed by linkage mapper and must be # reset here arcpy.env.cellSize = res_ras arcpy.env.extent = res_ras arcpy.env.snapRaster = res_ras arcpy.env.scratchWorkspace = output_gdb arcpy.env.workspace = output_gdb gprint('Finding restoration circles with max barrier score / ROI') # Find points with max ROI prefix = os.path.basename(proj_dir) if barrier_combine_method == 'Sum': sum_suffix = 'Sum' else: sum_suffix = '' barrier_fn = (prefix + "_BarrierCenters" + sum_suffix + "_Rad" + str(radius)) barrier_ras = os.path.join(proj_dir, 'output', 'barriers.gdb', barrier_fn) if not arcpy.Exists(barrier_ras): msg = ('Error: cannot find barrier output: ' + barrier_ras) lu.raise_error(msg) if cur_iter > 1: gprint('Creating mask for previously restored areas') in_neighborhood = arcpy.sa.NbrCircle(radius, "MAP") arcpy.env.extent = all_restored_areas_ras out_focal_stats = arcpy.sa.FocalStatistics( all_restored_areas_ras, in_neighborhood, "MEAN", "DATA") all_restored_focal_ras = os.path.join( output_gdb, 'allRestFocRas_iter' + str(cur_iter)) # Anything > 0 would include a restored area out_focal_stats.save(all_restored_focal_ras) arcpy.env.extent = res_ras rest_mask_ras = os.path.join( output_gdb, 'restMaskRaster_iter' + str(cur_iter)) minval = 0 out_con = arcpy.sa.Con( (arcpy.sa.Raster(all_restored_focal_ras) == float(minval)), 1) out_con.save(rest_mask_ras) # Candidate areas have not been restored, have cost data, meet # minimum improvement score criteria, and have enough ag in them candidate_barrier_ras = os.path.join( output_gdb, 'candidateBarrierRaster' + '_iter' + str(cur_iter)) if cur_iter > 1: gprint('Creating candidate restoration raster using barrier ' 'results, previous restorations, and selection ' 'criteria') # ROI scores will be in terms of total improvement # (= score * diameter) out_calc = (arcpy.sa.Raster(cost_mask_ras) * arcpy.sa.Raster(ag_mask_ras) * arcpy.sa.Raster(barrier_ras) * arcpy.sa.Raster(rest_mask_ras) * (radius * 2)) else: out_calc = (arcpy.sa.Raster(cost_mask_ras) * arcpy.sa.Raster(ag_mask_ras) * arcpy.sa.Raster(barrier_ras) * radius * 2) min_barrier_score = min_improvement_val * radius * 2 if restored_resistance_val != 1: out_calc_2 = (out_calc - (2 * radius * (restored_resistance_val - 1))) out_con = arcpy.sa.Con( (out_calc_2 >= float(min_barrier_score)), out_calc_2) else: out_con = arcpy.sa.Con((out_calc >= float(min_barrier_score)), out_calc) out_con.save(candidate_barrier_ras) lu.build_stats(candidate_barrier_ras) purchase_roi_ras = os.path.join( output_gdb, 'purchaseRoiRaster' + '_iter' + str(cur_iter)) out_calc = (arcpy.sa.Raster(candidate_barrier_ras) / arcpy.sa.Raster(purch_cost_ras)) out_calc.save(purchase_roi_ras) lu.build_stats(purchase_roi_ras) total_roi_ras = os.path.join( output_gdb, 'purchaseRestRoiRaster' + '_iter' + str(cur_iter)) out_calc = (arcpy.sa.Raster(candidate_barrier_ras) / arcpy.sa.Raster(total_cost_ras)) out_calc.save(total_roi_ras) lu.build_stats(total_roi_ras) max_barrier = float( arcpy.GetRasterProperties_management(candidate_barrier_ras, "MAXIMUM").getOutput(0)) gprint('Maximum barrier improvement score: ' + str(max_barrier)) if max_barrier < 0: arcpy.AddWarning("\nNo barriers found that meet CWD or Ag " "threshold criteria.") max_purch_roi = arcpy.GetRasterProperties_management( purchase_roi_ras, "MAXIMUM") gprint('Maximum purchase ROI score: ' + str(max_purch_roi.getOutput(0))) max_roi = arcpy.GetRasterProperties_management( total_roi_ras, "MAXIMUM") gprint('Maximum total ROI score: ' + str(max_roi.getOutput(0))) if restore_max_roi: out_point = os.path.join( output_gdb, 'maxRoiPoint' + '_iter' + str(cur_iter)) gprint('Choosing circle with maximum ROI to restore') out_con = arcpy.sa.Con( (arcpy.sa.Raster(total_roi_ras) >= float( max_roi.getOutput(0))), total_roi_ras) max_roi_ras = os.path.join(output_gdb, 'max_roi_ras') out_con.save(max_roi_ras) # Save max ROI to point try: arcpy.RasterToPoint_conversion(max_roi_ras, out_point) except Exception: msg = ('Error: it looks like there are no viable ' 'restoration candidates.') lu.raise_error(msg) else: # Restoring strongest barrier instead out_point = os.path.join( output_gdb, 'maxBarrierPoint' + '_iter' + str(cur_iter)) gprint('Choosing circle with maximum BARRIER IMPROVEMENT SCORE' ' to restore') out_con = arcpy.sa.Con( (arcpy.sa.Raster(candidate_barrier_ras) >= max_barrier), candidate_barrier_ras) max_barrier_ras = os.path.join(output_gdb, 'maxBarrierRaster') out_con.save(max_barrier_ras) # Save max barrier to point try: arcpy.RasterToPoint_conversion(max_barrier_ras, out_point) except Exception: msg = ('Error: it looks like there are no viable ' 'restoration candidates.') lu.raise_error(msg) gprint('Done evaluating candidate restorations') result = int(arcpy.GetCount_management(out_point).getOutput(0)) if result > 1: # Would be better to retain point with max barrier score when # we have multiple points with same ROI arcpy.AddWarning('Deleting points with identical ' 'ROI/improvement score values') arcpy.DeleteIdentical_management(out_point, "grid_code", 0.1, 0.1) arcpy.sa.ExtractMultiValuesToPoints( out_point, [[candidate_barrier_ras, "barrierScore"], [purch_cost_ras, "purchCost"], [total_cost_ras, "totalCost"], [purchase_roi_ras, "purchaseROI"], [total_roi_ras, "totalROI"]], "NONE") arcpy.AddField_management(out_point, "restorationNumber", "SHORT") arcpy.CalculateField_management(out_point, "restorationNumber", cur_iter, "PYTHON_9.3") arcpy.AddField_management(out_point, "radius", "DOUBLE") arcpy.CalculateField_management(out_point, "radius", radius, "PYTHON_9.3") arcpy.AddField_management(out_point, "barrierScore_per_m", "DOUBLE") arcpy.CalculateField_management( out_point, "barrierScore_per_m", "(float(!barrierScore!) / (!radius! * 2))", "PYTHON_9.3") gprint('\nCreating restoration circles') if restore_max_roi: circle_fc = os.path.join( output_gdb, 'maxRoiCircle' + '_iter' + str(cur_iter)) else: circle_fc = os.path.join( output_gdb, 'maxBarrierCircle' + '_iter' + str(cur_iter)) arcpy.Buffer_analysis(out_point, circle_fc, radius) gprint('Rasterizing restoration circles') if restore_max_roi: circle_ras = os.path.join( output_gdb, 'maxRoicircle_ras' + '_iter' + str(cur_iter)) else: circle_ras = os.path.join( output_gdb, 'maxBarrierCircleRas' + '_iter' + str(cur_iter)) arcpy.FeatureToRaster_conversion(circle_fc, 'totalROI', circle_ras, arcpy.env.cellSize) # restore raster gprint('Digitally restoring resistance raster') res_ras_restored = os.path.join( output_gdb, 'resRastRestored' + '_iter' + str(cur_iter)) out_con = arcpy.sa.Con(arcpy.sa.IsNull(circle_ras), res_ras, restored_resistance_val) out_con.save(res_ras_restored) all_restored_areas_ras = os.path.join( output_gdb, 'allRestoredAreas_iter' + str(cur_iter)) prev_restored_areas_ras = os.path.join( output_gdb, 'allRestoredAreas_iter' + str(cur_iter - 1)) if cur_iter == 1: out_con = arcpy.sa.Con(arcpy.sa.IsNull(circle_ras), 0, 1) else: # Add this restoration to areas restored out_con = arcpy.sa.Con(arcpy.sa.IsNull(circle_ras), prev_restored_areas_ras, 1) out_con.save(all_restored_areas_ras) lu.delete_data(circle_ras) # Use for next iteration resistance raster res_ras = res_ras_restored # Add circle into feature class with all circles if restore_max_roi: all_circles_fc = os.path.join(output_gdb, "allCirclesMaxROI") else: all_circles_fc = os.path.join(output_gdb, "allCirclesMaxBarriers") if cur_iter == 1: arcpy.CopyFeatures_management(circle_fc, all_circles_fc) else: arcpy.Append_management(circle_fc, all_circles_fc, "TEST") gprint('Finished iteration #' + str(cur_iter)) start_time1 = lu.elapsed_time(start_time1) gprint('\nDone with iterations.') start_time = lu.elapsed_time(start_time) gprint('Outputs saved in: ' + output_gdb) gprint('Back up your project directories if you want to save ' 'corridor/barrier results.') # Return GEOPROCESSING specific errors except arcpy.ExecuteError: lu.dashline(1) gprint('****Iteration script failed. Details follow.****') lu.exit_with_geoproc_error(_SCRIPT_NAME) # Return any PYTHON or system specific errors except Exception: lu.dashline(1) gprint('****Iteration script failed. Details follow.****') lu.exit_with_python_error(_SCRIPT_NAME)
def main(): """Iterates over LM, BM, and restoration tasks""" ## USER SETTINGS ###################################################### ## Restoration Settings ## ALL input data must be in the same projection start_time = time.clock() restoreMaxROI = False # Set to True to restore highest ROI # Set to False to restore strongest barrier restoredResistanceVal = 1 # Resistance value of restored habitat. Must be 1 or greater. restorationDataGDB = ( "C:\\barrierClassAnalysis\\RestorationINPUTS_July2013.gdb" ) # No spaces or special chars in paths or gdb names outputDir = "C:\\barrierClassAnalysis\\output" # No spaces in path, avoid using dropbox or network drive # Project directories will be created in this (iter1, iter2...) # as will an output geodatabase resistanceRaster = "URWA_resis" # Resistance raster. Should be in input GDB coreFC = "URWA_HCAs_Doug_Grant" # Core area feature class. Should be in input GDB 'URWA_HCAs_Doug_Grant' coreFN = "HCA_ID" # Core area field name radius = 450 # restoration radius in meters iterations = 13 # number of restorations to perform minAgThreshold = 0.75 # if less than this proportion of ag in circle, don't consider restoring circle minImprovementVal = ( 0 ) # Don't consider barriers below this improvement score (average improvement per meter diameter restored) parcelCostRaster = ( "DougGrantParcelCost_m2_projected_90m" ) # Average per-m2 parcel cost per pixel. Snapped to resistance raster. restorationCostRaster = "restCostPer_m2" # Right now this is just a raster with all pixels set to 0.113174 agRaster = "ARESmaskp_projected" # 1=Ag, 0 = not Ag barrierCombineMethod = "Maximum" # Some restorations benefit multiple corridors. # 'Maximum' takes the greatest improvement across core area pairs # 'Sum' adds improvement scores acreoss all pairs. cwdThresh = None # Use cwdThresh = None for no threshold. Use cwdThresh = X to not consider # restorations more than X map units away from each core area. ## END USER SETTINGS ###################################################### try: # Setup path and create directories gprint("Hey! Make sure everything is in the same projection!\n") gprint("Setting up paths and creating directories") sys.path.append("..\\toolbox\\scripts") resRast = os.path.join(restorationDataGDB, resistanceRaster) coreFCPath = os.path.join(restorationDataGDB, coreFC) # Set up a NEW output gdb (leave previous ones on drive) for i in range(1, 200): outputGDB = "restorationOutput" + str(i) + ".gdb" if not arcpy.Exists(os.path.join(outputDir, outputGDB)): break gprint("Previous output GDB " + outputGDB + " exists. Delete to save disk space.") arcpy.CreateFileGDB_management(outputDir, outputGDB) outputGDB = os.path.join(outputDir, outputGDB) logFile = os.path.join(outputGDB, "Iterate Barriers" + str(i) + ".py") shutil.copyfile(__file__, logFile) # write a copy of this file to output dir as a record of settings arcpy.env.cellSize = resRast arcpy.env.extent = resRast arcpy.env.snapRaster = resRast arcpy.env.overwriteOutput = True arcpy.env.scratchWorkspace = outputGDB arcpy.env.workspace = outputGDB spatialref = arcpy.Describe(resRast).spatialReference mapunits = spatialref.linearUnitName gprint("Cell size = " + str(arcpy.env.cellSize) + " " + mapunits + "s") # Calculate fraction of ag within radius of each pixel gprint("Calculating purchase cost, fraction of ag, etc within radius of each pixel.") agRaster = os.path.join(restorationDataGDB, agRaster) inNeighborhood = NbrCircle(radius, "MAP") arcpy.env.extent = agRaster outFocalStats = arcpy.sa.FocalStatistics(agRaster, inNeighborhood, "MEAN", "NODATA") proportionAgRaster = os.path.join(outputGDB, "proportionAgRas") outFocalStats.save(proportionAgRaster) arcpy.env.extent = resRast # Calculate purchase cost of circles parcelCostRaster = os.path.join(restorationDataGDB, parcelCostRaster) arcpy.env.extent = parcelCostRaster outFocalStats = arcpy.sa.FocalStatistics(parcelCostRaster, inNeighborhood, "MEAN", "DATA") costFocalStatsRaster = os.path.join(outputGDB, "costFocalStatsRaster") outFocalStats.save(costFocalStatsRaster) arcpy.env.extent = resRast circleArea = float(npy.pi * radius * radius) outras = Raster(costFocalStatsRaster) * circleArea purchCostRaster = os.path.join(outputGDB, "purchaseCostRaster") outras.save(purchCostRaster) lu.delete_data(costFocalStatsRaster) # restCost = npy.pi * radius * radius * restCostPer_m2 restorationCostRaster = os.path.join(restorationDataGDB, restorationCostRaster) outras = Raster(purchCostRaster) + (Raster(restorationCostRaster) * radius * radius * npy.pi) totalCostRaster = os.path.join(outputGDB, "totalCostRaster") outras.save(totalCostRaster) # lu.build_stats(totalCostRaster) # Create mask to remove areas without cost data arcpy.env.extent = totalCostRaster costMaskRaster = os.path.join(outputGDB, "costMaskRaster") costThresh = 0 outCon = arcpy.sa.Con((Raster(totalCostRaster) > float(costThresh)), 1) outCon.save(costMaskRaster) arcpy.env.extent = resRast # Create mask to remove areas below ag threshold outCon = arcpy.sa.Con((Raster(proportionAgRaster) > float(minAgThreshold)), 1) agMaskRaster = os.path.join(outputGDB, "agMaskRaster") outCon.save(agMaskRaster) doStep1 = "true" doStep2 = "true" doStep5 = "false" for iter in range(1, iterations + 1): # xxx start_time1 = time.clock() arcpy.env.cellSize = resRast # Some env settings get changed by linkage mapper and must be reset here arcpy.env.extent = resRast arcpy.env.snapRaster = resRast arcpy.env.overwriteOutput = True arcpy.env.scratchWorkspace = outputGDB arcpy.env.workspace = outputGDB lu.dashline(1) gprint("Running iteration number " + str(iter)) projDir = os.path.join(outputDir, "iter" + str(iter) + "Proj") lu.create_dir(outputDir) lu.delete_dir(projDir) # xxx lu.create_dir(projDir) if iter > 1: # Copy previous s2 linktable to new project directory datapassDir = os.path.join(projDir, "datapass") lu.create_dir(datapassDir) projDir1 = os.path.join(outputDir, "iter1Proj") datapassDirIter1 = os.path.join(projDir1, "datapass") s2LinktableIter1 = os.path.join(datapassDirIter1, "linkTable_s2.csv") s2LinkTable = os.path.join(datapassDir, "linkTable_s2.csv") shutil.copyfile(s2LinktableIter1, s2LinkTable) # Run Linkage Mapper distFile = os.path.join( outputDir, coreFC + "_dists.txt" ) # Copy distances text file from earlier LM run to the output directory- speeds things up! if not os.path.exists(distFile): if iter == 1: gprint("Will calculate distance file.") distFile = "#" else: projDir1 = os.path.join(outputDir, "iter1Proj") distFile1 = os.path.join(projDir1, coreFC + "_dists.txt") shutil.copyfile(distFile1, distFile) # Put a copy here for future runs arcpy.env.overwriteOutput = True arcpy.env.scratchWorkspace = outputGDB arcpy.env.workspace = outputGDB argv = ( "lm_master.py", projDir, coreFCPath, coreFN, resRast, doStep1, doStep2, "Cost-Weighted & Euclidean", distFile, "true", "true", "false", "4", "Cost-Weighted", "true", doStep5, "10000", "#", "#", ) gprint("Running " + str(argv)) import lm_master # xxx lm_master.lm_master(argv) # xxx doStep1 = "false" # Can skip for future iterations doStep2 = "false" # Can skip for future iterations doStep5 = "false" # Skipping for future iterations startRadius = str(radius) endRadius = str(radius) radiusStep = "0" saveRadiusRasters = "false" writePctRasters = "false" argv = ( "barrier_master.py", projDir, resRast, startRadius, endRadius, radiusStep, barrierCombineMethod, saveRadiusRasters, writePctRasters, cwdThresh, ) gprint("Running " + str(argv)) import barrier_master # xxx barrier_master.bar_master(argv) # xxx arcpy.env.cellSize = resRast # Some env settings get changed by linkage mapper and must be reset here arcpy.env.extent = resRast arcpy.env.snapRaster = resRast arcpy.env.overwriteOutput = True arcpy.env.scratchWorkspace = outputGDB arcpy.env.workspace = outputGDB gprint("Finding restoration circles with max barrier score / ROI") # Find points with max ROI PREFIX = os.path.basename(projDir) if barrierCombineMethod == "Sum": sumSuffix = "Sum" else: sumSuffix = "" barrierFN = PREFIX + "_BarrierCenters" + sumSuffix + "_Rad" + str(radius) barrierRaster = os.path.join(projDir, "output", "barriers.gdb", barrierFN) if not arcpy.Exists(barrierRaster): msg = "Error: cannot find barrier output: " + barrierRaster lu.raise_error(msg) # arcpy.env.cellSize = agMaskRaster # arcpy.env.extent = agMaskRaster if iter > 1: gprint("Creating mask for previously restored areas") inNeighborhood = NbrCircle(radius, "MAP") arcpy.env.extent = allRestoredAreasRaster outFocalStats = arcpy.sa.FocalStatistics(allRestoredAreasRaster, inNeighborhood, "MEAN", "DATA") allRestoredFocalRaster = os.path.join(outputGDB, "allRestFocRas_iter" + str(iter)) outFocalStats.save(allRestoredFocalRaster) # Anything > 0 would include a restored area and arcpy.env.extent = resRast restMaskRaster = os.path.join(outputGDB, "restMaskRaster_iter" + str(iter)) minval = 0 outCon = arcpy.sa.Con((Raster(allRestoredFocalRaster) == float(minval)), 1) outCon.save(restMaskRaster) # Candidate areas have not been restored, have cost data, meet # minimum improvement score criteria, and have enough ag in them candidateBarrierRaster = os.path.join(outputGDB, "candidateBarrierRaster" + "_iter" + str(iter)) if iter > 1: gprint( "Creating candidate restoration raster using barrier results, previous restorations, and selection criteria" ) outCalc = ( Raster(costMaskRaster) * Raster(agMaskRaster) * Raster(barrierRaster) * Raster(restMaskRaster) * (radius * 2) ) # ROI scores will be in terms of total improvement (= score * diameter) else: outCalc = Raster(costMaskRaster) * Raster(agMaskRaster) * Raster(barrierRaster) * radius * 2 minBarrierScore = minImprovementVal * radius * 2 if restoredResistanceVal != 1: outCalc2 = outCalc - (2 * radius * (restoredResistanceVal - 1)) outCon = arcpy.sa.Con((outCalc2 >= float(minBarrierScore)), outCalc2) else: outCon = arcpy.sa.Con((outCalc >= float(minBarrierScore)), outCalc) outCon.save(candidateBarrierRaster) lu.build_stats(candidateBarrierRaster) purchaseRoiRaster = os.path.join(outputGDB, "purchaseRoiRaster" + "_iter" + str(iter)) outCalc = Raster(candidateBarrierRaster) / Raster(purchCostRaster) outCalc.save(purchaseRoiRaster) lu.build_stats(purchaseRoiRaster) totalRoiRaster = os.path.join(outputGDB, "purchaseRestRoiRaster" + "_iter" + str(iter)) outCalc = Raster(candidateBarrierRaster) / Raster(totalCostRaster) outCalc.save(totalRoiRaster) lu.build_stats(totalRoiRaster) maxBarrier = arcpy.GetRasterProperties_management(candidateBarrierRaster, "MAXIMUM") gprint("Maximum barrier improvement score: " + str(maxBarrier.getOutput(0))) if maxBarrier < 0: arcpy.AddWarning("\nNo barriers found that meet CWD or Ag threshold criteria.") maxPurchROI = arcpy.GetRasterProperties_management(purchaseRoiRaster, "MAXIMUM") gprint("Maximum purchase ROI score: " + str(maxPurchROI.getOutput(0))) maxROI = arcpy.GetRasterProperties_management(totalRoiRaster, "MAXIMUM") gprint("Maximum total ROI score: " + str(maxROI.getOutput(0))) if restoreMaxROI: outPoint = os.path.join(outputGDB, "maxRoiPoint" + "_iter" + str(iter)) gprint("Choosing circle with maximum ROI to restore") outCon = arcpy.sa.Con((Raster(totalRoiRaster) >= float(maxROI.getOutput(0))), totalRoiRaster) maxRoiRaster = os.path.join(outputGDB, "maxRoiRaster") outCon.save(maxRoiRaster) # Save max ROI to point try: arcpy.RasterToPoint_conversion(maxRoiRaster, outPoint) except: msg = "Error: it looks like there are no viable restoration candidates." lu.raise_error(msg) else: # Restoring strongest barrier instead outPoint = os.path.join(outputGDB, "maxBarrierPoint" + "_iter" + str(iter)) gprint("Choosing circle with maximum BARRIER IMPROVEMENT SCORE to restore") outCon = arcpy.sa.Con( (Raster(candidateBarrierRaster) >= float(maxBarrier.getOutput(0))), candidateBarrierRaster ) maxBarrierRaster = os.path.join(outputGDB, "maxBarrierRaster") outCon.save(maxBarrierRaster) # Save max barrier to point try: arcpy.RasterToPoint_conversion(maxBarrierRaster, outPoint) except: msg = "Error: it looks like there are no viable restoration candidates." lu.raise_error(msg) gprint("Done evaluating candidate restorations") result = int(arcpy.GetCount_management(outPoint).getOutput(0)) if result > 1: arcpy.AddWarning( "Deleting points with identical ROI/improvement score values" ) # Would be better to retain point with max barrier score when we have multiple points with same ROI arcpy.DeleteIdentical_management(outPoint, "grid_code", 0.1, 0.1) arcpy.sa.ExtractMultiValuesToPoints( outPoint, [ [candidateBarrierRaster, "barrierScore"], [purchCostRaster, "purchCost"], [totalCostRaster, "totalCost"], [purchaseRoiRaster, "purchaseROI"], [totalRoiRaster, "totalROI"], ], "NONE", ) arcpy.AddField_management(outPoint, "restorationNumber", "SHORT") arcpy.CalculateField_management(outPoint, "restorationNumber", iter) arcpy.AddField_management(outPoint, "radius", "DOUBLE") arcpy.CalculateField_management(outPoint, "radius", radius) arcpy.AddField_management(outPoint, "barrierScore_per_m", "DOUBLE") arcpy.CalculateField_management( outPoint, "barrierScore_per_m", "(float(!barrierScore!) / (!radius! * 2))", "PYTHON" ) gprint("\nCreating restoration circles") if restoreMaxROI: circleFC = os.path.join(outputGDB, "maxRoiCircle" + "_iter" + str(iter)) else: circleFC = os.path.join(outputGDB, "maxBarrierCircle" + "_iter" + str(iter)) arcpy.Buffer_analysis(outPoint, circleFC, radius) gprint("Rasterizing restoration circles") if restoreMaxROI: circleRas = os.path.join(outputGDB, "maxRoiCircleRas" + "_iter" + str(iter)) else: circleRas = os.path.join(outputGDB, "maxBarrierCircleRas" + "_iter" + str(iter)) arcpy.FeatureToRaster_conversion(circleFC, "totalROI", circleRas, arcpy.env.cellSize) # restore raster gprint("Digitally restoring resistance raster") resRastRestored = os.path.join(outputGDB, "resRastRestored" + "_iter" + str(iter)) outCon = arcpy.sa.Con(IsNull(circleRas), resRast, restoredResistanceVal) outCon.save(resRastRestored) allRestoredAreasRaster = os.path.join(outputGDB, "allRestoredAreas_iter" + str(iter)) PrevRestoredAreasRaster = os.path.join(outputGDB, "allRestoredAreas_iter" + str(iter - 1)) if iter == 1: outCon = arcpy.sa.Con(IsNull(circleRas), 0, 1) else: outCon = arcpy.sa.Con( IsNull(circleRas), PrevRestoredAreasRaster, 1 ) # Add this restoration to areas restored outCon.save(allRestoredAreasRaster) lu.delete_data(circleRas) resRast = resRastRestored # Use for next iteration resistance raster # Add circle into feature class with all circles if restoreMaxROI: allCirclesFC = os.path.join(outputGDB, "allCirclesMaxROI") else: allCirclesFC = os.path.join(outputGDB, "allCirclesMaxBarriers") if iter == 1: arcpy.CopyFeatures_management(circleFC, allCirclesFC) else: arcpy.Append_management(circleFC, allCirclesFC, "TEST") gprint("Finished iteration #" + str(iter)) start_time1 = lu.elapsed_time(start_time1) gprint("\nDone with iterations.") start_time = lu.elapsed_time(start_time) gprint("Outputs saved in: " + outputGDB) gprint("Back up your project directories if you want to save corridor/barrier results.") # Return GEOPROCESSING specific errors except arcpy.ExecuteError: lu.dashline(1) gprint("****Iteration script failed. Details follow.****") lu.exit_with_geoproc_error(_SCRIPT_NAME) # Return any PYTHON or system specific errors except: lu.dashline(1) gprint("****Iteration script failed. Details follow.****") lu.exit_with_python_error(_SCRIPT_NAME)
def main(): """Iterates over LM, BM, and restoration tasks""" ## USER SETTINGS ###################################################### ## Restoration Settings ## ALL input data must be in the same projection start_time = time.clock() restoreMaxROI = False # Set to True to restore highest ROI # Set to False to restore strongest barrier restoredResistanceVal = 1 # Resistance value of restored habitat. Must be 1 or greater. restorationDataGDB = "C:\\barrierClassAnalysis\\RestorationINPUTS_July2013.gdb" # No spaces or special chars in paths or gdb names outputDir = "C:\\barrierClassAnalysis\\output" # No spaces in path, avoid using dropbox or network drive # Project directories will be created in this (iter1, iter2...) # as will an output geodatabase resistanceRaster = "URWA_resis"# Resistance raster. Should be in input GDB coreFC = 'URWA_HCAs_Doug_Grant'# Core area feature class. Should be in input GDB 'URWA_HCAs_Doug_Grant' coreFN = 'HCA_ID' # Core area field name radius = 450 # restoration radius in meters iterations = 13 # number of restorations to perform minAgThreshold = 0.75 # if less than this proportion of ag in circle, don't consider restoring circle minImprovementVal = 0 # Don't consider barriers below this improvement score (average improvement per meter diameter restored) parcelCostRaster = 'DougGrantParcelCost_m2_projected_90m' # Average per-m2 parcel cost per pixel. Snapped to resistance raster. restorationCostRaster = 'restCostPer_m2' # Right now this is just a raster with all pixels set to 0.113174 agRaster = "ARESmaskp_projected" # 1=Ag, 0 = not Ag barrierCombineMethod = 'Maximum' # Some restorations benefit multiple corridors. # 'Maximum' takes the greatest improvement across core area pairs # 'Sum' adds improvement scores acreoss all pairs. cwdThresh = None # Use cwdThresh = None for no threshold. Use cwdThresh = X to not consider # restorations more than X map units away from each core area. ## END USER SETTINGS ###################################################### try: # Setup path and create directories gprint('Hey! Make sure everything is in the same projection!\n') gprint('Setting up paths and creating directories') sys.path.append('..\\toolbox\\scripts') resRast = os.path.join(restorationDataGDB, resistanceRaster) coreFCPath = os.path.join(restorationDataGDB, coreFC) # Set up a NEW output gdb (leave previous ones on drive) for i in range (1,200): outputGDB = 'restorationOutput'+str(i)+'.gdb' if not arcpy.Exists(os.path.join(outputDir,outputGDB)): break gprint('Previous output GDB '+ outputGDB +' exists. Delete to save disk space.') arcpy.CreateFileGDB_management(outputDir,outputGDB) outputGDB = os.path.join(outputDir,outputGDB) logFile = os.path.join(outputGDB,'Iterate Barriers'+str(i)+'.py') shutil.copyfile(__file__, logFile) #write a copy of this file to output dir as a record of settings arcpy.env.cellSize = resRast arcpy.env.extent = resRast arcpy.env.snapRaster = resRast arcpy.env.overwriteOutput = True arcpy.env.scratchWorkspace = outputGDB arcpy.env.workspace = outputGDB spatialref = arcpy.Describe(resRast).spatialReference mapunits = spatialref.linearUnitName gprint('Cell size = ' + str(arcpy.env.cellSize) + ' ' + mapunits +'s') # Calculate fraction of ag within radius of each pixel gprint('Calculating purchase cost, fraction of ag, etc within radius of each pixel.') agRaster = os.path.join(restorationDataGDB, agRaster) inNeighborhood = NbrCircle(radius, "MAP") arcpy.env.extent = agRaster outFocalStats = arcpy.sa.FocalStatistics(agRaster, inNeighborhood, "MEAN","NODATA") proportionAgRaster = os.path.join(outputGDB,'proportionAgRas') outFocalStats.save(proportionAgRaster) arcpy.env.extent = resRast # Calculate purchase cost of circles parcelCostRaster = os.path.join(restorationDataGDB, parcelCostRaster) arcpy.env.extent = parcelCostRaster outFocalStats = arcpy.sa.FocalStatistics(parcelCostRaster,inNeighborhood, "MEAN","DATA") costFocalStatsRaster = os.path.join(outputGDB,'costFocalStatsRaster') outFocalStats.save(costFocalStatsRaster) arcpy.env.extent = resRast circleArea = float(npy.pi * radius * radius) outras = (Raster(costFocalStatsRaster) * circleArea) purchCostRaster = os.path.join(outputGDB,'purchaseCostRaster') outras.save(purchCostRaster) lu.delete_data(costFocalStatsRaster) # restCost = npy.pi * radius * radius * restCostPer_m2 restorationCostRaster = os.path.join(restorationDataGDB, restorationCostRaster) outras = Raster(purchCostRaster) + (Raster(restorationCostRaster) * radius * radius * npy.pi) totalCostRaster = os.path.join(outputGDB,'totalCostRaster') outras.save(totalCostRaster) # lu.build_stats(totalCostRaster) # Create mask to remove areas without cost data arcpy.env.extent = totalCostRaster costMaskRaster = os.path.join(outputGDB,'costMaskRaster') costThresh = 0 outCon = arcpy.sa.Con((Raster(totalCostRaster) > float(costThresh)), 1) outCon.save(costMaskRaster) arcpy.env.extent = resRast # Create mask to remove areas below ag threshold outCon = arcpy.sa.Con((Raster(proportionAgRaster) > float(minAgThreshold)), 1) agMaskRaster = os.path.join(outputGDB, 'agMaskRaster') outCon.save(agMaskRaster) doStep1 = 'true' doStep2 = 'true' doStep5 = 'false' for iter in range(1,iterations+1): #xxx start_time1 = time.clock() arcpy.env.cellSize = resRast # Some env settings get changed by linkage mapper and must be reset here arcpy.env.extent = resRast arcpy.env.snapRaster = resRast arcpy.env.overwriteOutput = True arcpy.env.scratchWorkspace = outputGDB arcpy.env.workspace = outputGDB lu.dashline(1) gprint('Running iteration number '+str(iter)) projDir = os.path.join(outputDir,'iter' + str(iter)+'Proj') lu.create_dir(outputDir) lu.delete_dir(projDir) #xxx lu.create_dir(projDir) if iter > 1: # Copy previous s2 linktable to new project directory datapassDir = os.path.join(projDir,'datapass') lu.create_dir(datapassDir) projDir1 = os.path.join(outputDir,'iter1Proj') datapassDirIter1 = os.path.join(projDir1,'datapass') s2LinktableIter1 = os.path.join(datapassDirIter1 ,'linkTable_s2.csv') s2LinkTable = os.path.join(datapassDir ,'linkTable_s2.csv') shutil.copyfile(s2LinktableIter1, s2LinkTable) # Run Linkage Mapper distFile = os.path.join(outputDir, coreFC + '_dists.txt') # Copy distances text file from earlier LM run to the output directory- speeds things up! if not os.path.exists(distFile): if iter == 1: gprint('Will calculate distance file.') distFile = '#' else: projDir1 = os.path.join(outputDir,'iter1Proj') distFile1 = os.path.join(projDir1, coreFC + '_dists.txt') shutil.copyfile(distFile1,distFile) # Put a copy here for future runs arcpy.env.overwriteOutput = True arcpy.env.scratchWorkspace = outputGDB arcpy.env.workspace = outputGDB argv = ('lm_master.py', projDir, coreFCPath, coreFN, resRast, doStep1, doStep2, 'Cost-Weighted & Euclidean', distFile, 'true', 'true', 'false', '4', 'Cost-Weighted', 'true', doStep5, 'true', '200000', '10000', '#', '#', '#', '#') gprint('Running ' + str(argv)) cfg.lm_configured = False # Insures lm_master uses current argv lm_master.lm_master(argv) #xxx doStep1 = 'false' # Can skip for future iterations doStep2 = 'false' # Can skip for future iterations doStep5 = 'false' # Skipping for future iterations startRadius = str(radius) endRadius = str(radius) radiusStep = '0' saveRadiusRasters= 'false' writePctRasters = 'false' argv = ('barrier_master.py', projDir, resRast, startRadius, endRadius, radiusStep, barrierCombineMethod, saveRadiusRasters, writePctRasters, cwdThresh) gprint('Running ' + str(argv)) barrier_master.bar_master(argv) #xxx arcpy.env.cellSize = resRast # Some env settings get changed by linkage mapper and must be reset here arcpy.env.extent = resRast arcpy.env.snapRaster = resRast arcpy.env.overwriteOutput = True arcpy.env.scratchWorkspace = outputGDB arcpy.env.workspace = outputGDB gprint('Finding restoration circles with max barrier score / ROI') # Find points with max ROI PREFIX = os.path.basename(projDir) if barrierCombineMethod == 'Sum': sumSuffix = 'Sum' else: sumSuffix = '' barrierFN = (PREFIX + "_BarrierCenters" + sumSuffix + "_Rad" + str(radius)) barrierRaster = os.path.join(projDir,'output','barriers.gdb',barrierFN) if not arcpy.Exists(barrierRaster): msg = ('Error: cannot find barrier output: '+barrierRaster) lu.raise_error(msg) # arcpy.env.cellSize = agMaskRaster # arcpy.env.extent = agMaskRaster if iter > 1: gprint('Creating mask for previously restored areas') inNeighborhood = NbrCircle(radius, "MAP") arcpy.env.extent = allRestoredAreasRaster outFocalStats = arcpy.sa.FocalStatistics(allRestoredAreasRaster,inNeighborhood, "MEAN","DATA") allRestoredFocalRaster = os.path.join(outputGDB,'allRestFocRas_iter'+str(iter)) outFocalStats.save(allRestoredFocalRaster) # Anything > 0 would include a restored area and arcpy.env.extent = resRast restMaskRaster = os.path.join(outputGDB,'restMaskRaster_iter'+str(iter)) minval = 0 outCon = arcpy.sa.Con((Raster(allRestoredFocalRaster) == float(minval)), 1) outCon.save(restMaskRaster) # Candidate areas have not been restored, have cost data, meet # minimum improvement score criteria, and have enough ag in them candidateBarrierRaster = os.path.join(outputGDB, 'candidateBarrierRaster' + '_iter'+str(iter)) if iter > 1: gprint('Creating candidate restoration raster using barrier results, previous restorations, and selection criteria') outCalc = (Raster(costMaskRaster) * Raster(agMaskRaster) * Raster(barrierRaster) * Raster(restMaskRaster) * (radius * 2)) # ROI scores will be in terms of total improvement (= score * diameter) else: outCalc = (Raster(costMaskRaster) * Raster(agMaskRaster) * Raster(barrierRaster) * radius * 2) minBarrierScore = minImprovementVal * radius * 2 if restoredResistanceVal != 1: outCalc2 = (outCalc - (2 * radius * (restoredResistanceVal - 1))) outCon = arcpy.sa.Con((outCalc2 >= float(minBarrierScore)), outCalc2) else: outCon = arcpy.sa.Con((outCalc >= float(minBarrierScore)), outCalc) outCon.save(candidateBarrierRaster) lu.build_stats(candidateBarrierRaster) purchaseRoiRaster = os.path.join(outputGDB, 'purchaseRoiRaster' + '_iter'+str(iter)) outCalc = Raster(candidateBarrierRaster) / Raster(purchCostRaster) outCalc.save(purchaseRoiRaster) lu.build_stats(purchaseRoiRaster) totalRoiRaster = os.path.join(outputGDB, 'purchaseRestRoiRaster' + '_iter'+str(iter)) outCalc = Raster(candidateBarrierRaster) / Raster(totalCostRaster) outCalc.save(totalRoiRaster) lu.build_stats(totalRoiRaster) maxBarrier = arcpy.GetRasterProperties_management(candidateBarrierRaster,"MAXIMUM") gprint('Maximum barrier improvement score: '+str(maxBarrier.getOutput(0))) if maxBarrier < 0: arcpy.AddWarning("\nNo barriers found that meet CWD or Ag threshold criteria.") maxPurchROI = arcpy.GetRasterProperties_management(purchaseRoiRaster,"MAXIMUM") gprint('Maximum purchase ROI score: '+str(maxPurchROI.getOutput(0))) maxROI = arcpy.GetRasterProperties_management(totalRoiRaster,"MAXIMUM") gprint('Maximum total ROI score: '+str(maxROI.getOutput(0))) if restoreMaxROI: outPoint = os.path.join(outputGDB, 'maxRoiPoint'+'_iter'+str(iter)) gprint('Choosing circle with maximum ROI to restore') outCon = arcpy.sa.Con((Raster(totalRoiRaster) >= float(maxROI.getOutput(0))), totalRoiRaster) maxRoiRaster = os.path.join(outputGDB, 'maxRoiRaster') outCon.save(maxRoiRaster) # Save max ROI to point try: arcpy.RasterToPoint_conversion(maxRoiRaster, outPoint) except: msg = ('Error: it looks like there are no viable restoration candidates.') lu.raise_error(msg) else: #Restoring strongest barrier instead outPoint = os.path.join(outputGDB, 'maxBarrierPoint'+'_iter'+str(iter)) gprint('Choosing circle with maximum BARRIER IMPROVEMENT SCORE to restore') outCon = arcpy.sa.Con((Raster(candidateBarrierRaster) >= float(maxBarrier.getOutput(0))), candidateBarrierRaster) maxBarrierRaster = os.path.join(outputGDB, 'maxBarrierRaster') outCon.save(maxBarrierRaster) # Save max barrier to point try: arcpy.RasterToPoint_conversion(maxBarrierRaster, outPoint) except: msg = ('Error: it looks like there are no viable restoration candidates.') lu.raise_error(msg) gprint('Done evaluating candidate restorations') result = int(arcpy.GetCount_management(outPoint).getOutput(0)) if result > 1: arcpy.AddWarning('Deleting points with identical ROI/improvement score values') # Would be better to retain point with max barrier score when we have multiple points with same ROI arcpy.DeleteIdentical_management(outPoint, "grid_code", 0.1, 0.1) arcpy.sa.ExtractMultiValuesToPoints(outPoint, [[candidateBarrierRaster, "barrierScore"],[purchCostRaster, "purchCost"], [totalCostRaster, "totalCost"],[purchaseRoiRaster, "purchaseROI"], [totalRoiRaster, "totalROI"]], "NONE") arcpy.AddField_management(outPoint, "restorationNumber", "SHORT") arcpy.CalculateField_management(outPoint, "restorationNumber", iter) arcpy.AddField_management(outPoint, "radius", "DOUBLE") arcpy.CalculateField_management(outPoint, "radius", radius) arcpy.AddField_management(outPoint, "barrierScore_per_m", "DOUBLE") arcpy.CalculateField_management(outPoint, "barrierScore_per_m", "(float(!barrierScore!) / (!radius! * 2))", "PYTHON") gprint('\nCreating restoration circles') if restoreMaxROI: circleFC = os.path.join(outputGDB, 'maxRoiCircle'+'_iter'+str(iter)) else: circleFC = os.path.join(outputGDB, 'maxBarrierCircle'+'_iter'+str(iter)) arcpy.Buffer_analysis(outPoint, circleFC, radius) gprint('Rasterizing restoration circles') if restoreMaxROI: circleRas = os.path.join(outputGDB, 'maxRoiCircleRas'+'_iter'+str(iter)) else: circleRas = os.path.join(outputGDB, 'maxBarrierCircleRas'+'_iter'+str(iter)) arcpy.FeatureToRaster_conversion(circleFC, 'totalROI', circleRas, arcpy.env.cellSize) # restore raster gprint('Digitally restoring resistance raster') resRastRestored = os.path.join(outputGDB, 'resRastRestored'+'_iter'+str(iter)) outCon = arcpy.sa.Con(IsNull(circleRas), resRast, restoredResistanceVal) outCon.save(resRastRestored) allRestoredAreasRaster = os.path.join(outputGDB, 'allRestoredAreas_iter'+str(iter)) PrevRestoredAreasRaster= os.path.join(outputGDB, 'allRestoredAreas_iter'+str(iter-1)) if iter == 1: outCon = arcpy.sa.Con(IsNull(circleRas), 0, 1) else: outCon = arcpy.sa.Con(IsNull(circleRas), PrevRestoredAreasRaster, 1) # Add this restoration to areas restored outCon.save(allRestoredAreasRaster) lu.delete_data(circleRas) resRast = resRastRestored # Use for next iteration resistance raster #Add circle into feature class with all circles if restoreMaxROI: allCirclesFC = os.path.join(outputGDB,"allCirclesMaxROI") else: allCirclesFC = os.path.join(outputGDB,"allCirclesMaxBarriers") if iter == 1: arcpy.CopyFeatures_management(circleFC, allCirclesFC) else: arcpy.Append_management(circleFC, allCirclesFC, "TEST") gprint('Finished iteration #'+str(iter)) start_time1 = lu.elapsed_time(start_time1) gprint('\nDone with iterations.') start_time = lu.elapsed_time(start_time) gprint('Outputs saved in: '+outputGDB) gprint('Back up your project directories if you want to save corridor/barrier results.') # Return GEOPROCESSING specific errors except arcpy.ExecuteError: lu.dashline(1) gprint('****Iteration script failed. Details follow.****') lu.exit_with_geoproc_error(_SCRIPT_NAME) # Return any PYTHON or system specific errors except: lu.dashline(1) gprint('****Iteration script failed. Details follow.****') lu.exit_with_python_error(_SCRIPT_NAME)