def arc_wksp_setup(): """Setup ArcPy workspace""" arcpy.env.overwriteOutput = True arcpy.env.cellSize = "MAXOF" # Setting to default. For batch runs. if arcpy.Exists(cc_env.out_dir): cc_util.delete_features(cc_env.out_dir) arcpy.env.workspace = cc_util.mk_proj_dir(cc_env.out_dir) arcpy.env.scratchWorkspace = cc_util.mk_proj_dir(cc_env.tmp_dir)
def grass_cwd(core_list): """Creating CWD and Back rasters using GRASS r.walk function""" cur_path = subprocess.Popen("echo %PATH%", stdout=subprocess.PIPE, shell=True).stdout.read() gisdbase = os.path.join(cc_env.proj_dir, "gwksp") ccr_grassrc = os.path.join(cc_env.proj_dir, "ccr_grassrc") climate_asc = os.path.join(cc_env.out_dir, "cc_climate.asc") resist_asc = os.path.join(cc_env.out_dir, "cc_resist.asc") core_asc = os.path.join(cc_env.out_dir, "cc_cores.asc") climate_lyr = "climate" resist_lyr = "resist" core_lyr = "cores" try: lm_util.gprint("\nRUNNING GRASS TO CREATE COST-WEIGHTED DISTANCE " "RASTERS") # Convert input GRID rasters to ASCII lm_util.gprint("Converting ARCINFO GRID rasters to ASCII") # Note: consider moving these to main: arcpy.RasterToASCII_conversion(cc_env.prj_climate_rast, climate_asc) arcpy.RasterToASCII_conversion(cc_env.prj_resist_rast, resist_asc) arcpy.RasterToASCII_conversion(cc_env.prj_core_rast, core_asc) # Create resource file and setup workspace write_grassrc(ccr_grassrc, gisdbase) setup_wrkspace(gisdbase, ccr_grassrc, climate_asc) # Make cwd folder for Linkage Mapper lm_util.make_cwd_paths(max(core_list)) # Import files into GRASS lm_util.gprint("Importing raster files into GRASS") run_grass_cmd("r.in.arc", input=climate_asc, output=climate_lyr) run_grass_cmd("r.in.arc", input=resist_asc, output=resist_lyr) run_grass_cmd("r.in.arc", input=core_asc, output=core_lyr) # Generate CWD and Back rasters gen_cwd_back(core_list, climate_lyr, resist_lyr, core_lyr) except Exception: raise finally: os.environ['PATH'] = cur_path # Revert to original windows path if not cc_util.remove_grass_wkspc(gisdbase): arcpy.AddWarning("Unable to delete temporary GRASS folder. " "Program will contine.") cc_util.delete_features( [climate_asc, resist_asc, core_asc, ccr_grassrc])
def delete_proj_files(): """Delete project input files on ending of analysis Keep prj_resist_rast, prj_core_fc and out_dir for reruns. """ cpath = os.getcwd() # For files left behind by arcpy prj_files = ( [cc_env.prj_climate_rast, cc_env.prj_core_rast, cc_env.tmp_dir, os.path.join(cpath, ".prj"), os.path.join(cpath, "info")]) if cc_env.simplify_cores: prj_files.append(cc_env.core_simp) cc_util.delete_features(prj_files)
def grass_cwd(core_list): """Creating CWD and Back rasters using GRASS r.walk function""" gisdbase = os.path.join(cc_env.proj_dir, "gwksp") ccr_grassrc = os.path.join(cc_env.proj_dir, "ccr_grassrc") climate_asc = os.path.join(cc_env.out_dir, "cc_climate.asc") resist_asc = os.path.join(cc_env.out_dir, "cc_resist.asc") core_asc = os.path.join(cc_env.out_dir, "cc_cores.asc") climate_lyr = "climate" resist_lyr = "resist" core_lyr = "cores" try: lm_util.gprint("\nRUNNING GRASS TO CREATE COST-WEIGHTED DISTANCE " "RASTERS") # Convert input GRID rasters to ASCII lm_util.gprint("Converting ARCINFO GRID rasters to ASCII") arcpy.RasterToASCII_conversion(cc_env.prj_climate_rast, climate_asc) arcpy.RasterToASCII_conversion(cc_env.prj_resist_rast, resist_asc) arcpy.RasterToASCII_conversion(cc_env.prj_core_rast, core_asc) # Create resource file and setup workspace start_path = os.environ["PATH"] os.environ["PATH"] = cc_env.gpath write_grassrc(ccr_grassrc, gisdbase) setup_wrkspace(gisdbase, ccr_grassrc, climate_asc) # Make cwd folder for Linkage Mapper lm_util.make_cwd_paths(max(core_list)) # Import files into GRASS lm_util.gprint("Importing raster files into GRASS") run_grass_cmd("r.in.gdal", input=climate_asc, output=climate_lyr) run_grass_cmd("r.in.gdal", input=resist_asc, output=resist_lyr) run_grass_cmd("r.in.gdal", input=core_asc, output=core_lyr) # Generate CWD and Back rasters gen_cwd_back(core_list, climate_lyr, resist_lyr, core_lyr) except Exception: raise finally: os.environ["PATH"] = start_path if not cc_util.remove_grass_wkspc(gisdbase): lm_util.warn("Unable to delete temporary GRASS folder. " "Program will contine.") cc_util.delete_features( [climate_asc, resist_asc, core_asc, ccr_grassrc])
def delete_proj_files(): """Delete project input files on ending of analysis Keep prj_resist_rast, prj_core_fc and out_dir for reruns. """ cpath = os.getcwd() # For files left behind by arcpy prj_files = ([ cc_env.prj_climate_rast, cc_env.prj_core_rast, cc_env.tmp_dir, os.path.join(cpath, ".prj"), os.path.join(cpath, "info") ]) if cc_env.simplify_cores: prj_files.append(cc_env.core_simp) cc_util.delete_features(prj_files)
def limit_cores(pair_tbl, stats_tbl): """Limit core pairs based upon climate threshold""" pair_vw = "dist_tbvw" stats_vw = "stats_tbvw" core_id = cc_env.core_fld.upper() try: lm_util.gprint("\nLIMITING CORE PAIRS BASED UPON CLIMATE " "THRESHOLD") arcpy.MakeTableView_management(pair_tbl, pair_vw) arcpy.MakeTableView_management(stats_tbl, stats_vw) # Add basic stats to distance table lm_util.gprint("Joining zonal statistics to pairings table") add_stats(stats_vw, core_id, "fr", pair_vw, TO_COL) add_stats(stats_vw, core_id, "to", pair_vw, FR_COL) # Calculate difference of 2 std lm_util.gprint("Calculating difference of 2 std") diffu_2std = "diffu_2std" arcpy.AddField_management(pair_vw, diffu_2std, "Float", "", "", "", "", "NULLABLE") arcpy.CalculateField_management(pair_vw, diffu_2std, "abs(!frumin2std! - !toumin2std!)", "PYTHON") # Filter distance table based on inputed threshold and delete rows lm_util.gprint("Filtering table based on threshold") diffu2std_fld = arcpy.AddFieldDelimiters(pair_vw, diffu_2std) expression = diffu2std_fld + " <= " + str(cc_env.climate_threshold) arcpy.SelectLayerByAttribute_management(pair_vw, "NEW_SELECTION", expression) rows_del = int(arcpy.GetCount_management(pair_vw).getOutput(0)) if rows_del > 0: arcpy.DeleteRows_management(pair_vw) lm_util.gprint(str(rows_del) + " rows deleted") except Exception: raise finally: cc_util.delete_features([stats_vw, pair_vw])
def limit_cores(pair_tbl, stats_tbl): """Limit core pairs based upon climate threshold""" pair_vw = "dist_tbvw" stats_vw = "stats_tbvw" core_id = cc_env.core_fld.upper() try: lm_util.gprint("\nLIMITING CORE PAIRS BASED UPON CLIMATE " "THRESHOLD") arcpy.MakeTableView_management(pair_tbl, pair_vw) arcpy.MakeTableView_management(stats_tbl, stats_vw) # Add basic stats to distance table lm_util.gprint("Joining zonal statistics to pairings table") add_stats(stats_vw, core_id, "fr", pair_vw, TO_COL) add_stats(stats_vw, core_id, "to", pair_vw, FR_COL) # Calculate difference of 2 std lm_util.gprint("Calculating difference of 2 std") diffu_2std = "diffu_2std" arcpy.AddField_management(pair_vw, diffu_2std, "Float", "", "", "", "", "NULLABLE") arcpy.CalculateField_management(pair_vw, diffu_2std, "abs(!frumin2std! - !toumin2std!)", "PYTHON_9.3") # Filter distance table based on inputed threshold and delete rows lm_util.gprint("Filtering table based on threshold") diffu2std_fld = arcpy.AddFieldDelimiters(pair_vw, diffu_2std) expression = diffu2std_fld + " <= " + str(cc_env.climate_threshold) arcpy.SelectLayerByAttribute_management(pair_vw, "NEW_SELECTION", expression) rows_del = int(arcpy.GetCount_management(pair_vw).getOutput(0)) if rows_del > 0: arcpy.DeleteRows_management(pair_vw) lm_util.gprint(str(rows_del) + " rows deleted") except Exception: raise finally: cc_util.delete_features([stats_vw, pair_vw])
def create_lnk_tbl(corefc, core_pairs, frm_cores): """Create link table file and limit based on near table results""" fcore_vw = "fcore_vw" tcore_vw = "tcore_vw" jtocore_fn = cc_env.core_fld[:8] + "_1" # dbf field length near_tbl = os.path.join(cc_env.out_dir, "neartbl.dbf") link_file = os.path.join(lm_env.DATAPASSDIR, "linkTable_s2.csv") link_tbl, srow, srows = None, None, None try: link_tbl = open(link_file, 'wb') writer = csv.writer(link_tbl, delimiter=',') headings = [ "# link", "coreId1", "coreId2", "cluster1", "cluster2", "linkType", "eucDist", "lcDist", "eucAdj", "cwdAdj" ] writer.writerow(headings) core_list = set() no_cores = str(len(frm_cores)) i = 1 coreid_fld = arcpy.AddFieldDelimiters(corefc, cc_env.core_fld) for core_no, frm_core in enumerate(frm_cores): # From cores expression = coreid_fld + " = " + frm_core arcpy.MakeFeatureLayer_management(corefc, fcore_vw, expression) # To cores to_cores_lst = [x[1] for x in core_pairs if frm_core == x[0]] to_cores = ', '.join(to_cores_lst) expression = coreid_fld + " in (" + to_cores + ")" arcpy.MakeFeatureLayer_management(corefc, tcore_vw, expression) lm_util.gprint("Calculating Euclidean distance/s from Core " + frm_core + " to " + str(len(to_cores_lst)) + " other cores" + " (" + str(core_no + 1) + "/" + no_cores + ")") # Generate near table for these core pairings arcpy.GenerateNearTable_analysis(fcore_vw, tcore_vw, near_tbl, cc_env.max_euc_dist, "NO_LOCATION", "NO_ANGLE", "ALL") # Join near table to core table arcpy.JoinField_management(near_tbl, "IN_FID", corefc, "FID", cc_env.core_fld) arcpy.JoinField_management(near_tbl, "NEAR_FID", corefc, "FID", cc_env.core_fld) # Limit pairings based on inputed Euclidean distances srow, srows = None, None euc_dist_fld = arcpy.AddFieldDelimiters(near_tbl, "NEAR_DIST") expression = (euc_dist_fld + " > " + str(cc_env.min_euc_dist)) srows = arcpy.SearchCursor(near_tbl, expression, "", jtocore_fn + "; NEAR_DIST", jtocore_fn + " A; NEAR_DIST A") # Process near table and output into a link table srow = srows.next() if srow: core_list.add(int(frm_core)) while srow: to_coreid = srow.getValue(jtocore_fn) dist_value = srow.getValue("NEAR_DIST") writer.writerow([ i, frm_core, to_coreid, -1, -1, 1, dist_value, -1, -1, -1 ]) core_list.add(to_coreid) srow = srows.next() i += 1 except Exception: raise finally: cc_util.delete_features( [near_tbl, os.path.splitext(corefc)[0] + "_Pnt.shp"]) if link_tbl: link_tbl.close() if srow: del srow if srows: del srows return core_list
def cc_copy_inputs(): """Clip Climate Linkage Mapper inputs to smallest extent""" ext_poly = os.path.join(cc_env.out_dir, "ext_poly.shp") # Extent polygon try: lm_util.gprint("\nCOPYING LAYERS AND, IF NECESSARY, REDUCING EXTENT") if not arcpy.Exists(cc_env.inputs_gdb): arcpy.CreateFileGDB_management(os.path.dirname(cc_env.inputs_gdb), os.path.basename(cc_env.inputs_gdb)) 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) except Exception: raise finally: cc_util.delete_features(ext_poly)
def create_lnk_tbl(corefc, core_pairs, frm_cores): """Create link table file and limit based on near table results""" fcore_vw = "fcore_vw" tcore_vw = "tcore_vw" jtocore_fn = cc_env.core_fld[:8] + "_1" # dbf field length near_tbl = os.path.join(cc_env.out_dir, "neartbl.dbf") link_file = os.path.join(lm_env.DATAPASSDIR, "linkTable_s2.csv") link_tbl, srow, srows = None, None, None try: link_tbl = open(link_file, 'wb') writer = csv.writer(link_tbl, delimiter=',') headings = ["# link", "coreId1", "coreId2", "cluster1", "cluster2", "linkType", "eucDist", "lcDist", "eucAdj", "cwdAdj"] writer.writerow(headings) core_list = set() no_cores = str(len(frm_cores)) i = 1 coreid_fld = arcpy.AddFieldDelimiters(corefc, cc_env.core_fld) for core_no, frm_core in enumerate(frm_cores): # From cores expression = coreid_fld + " = " + frm_core arcpy.MakeFeatureLayer_management(corefc, fcore_vw, expression) # To cores to_cores_lst = [x[1] for x in core_pairs if frm_core == x[0]] to_cores = ', '.join(to_cores_lst) expression = coreid_fld + " in (" + to_cores + ")" arcpy.MakeFeatureLayer_management(corefc, tcore_vw, expression) lm_util.gprint("Calculating Euclidean distance/s from Core " + frm_core + " to " + str(len(to_cores_lst)) + " other cores" + " (" + str(core_no + 1) + "/" + no_cores + ")") # Generate near table for these core pairings arcpy.GenerateNearTable_analysis( fcore_vw, tcore_vw, near_tbl, cc_env.max_euc_dist, "NO_LOCATION", "NO_ANGLE", "ALL") # Join near table to core table arcpy.JoinField_management(near_tbl, "IN_FID", corefc, "FID", cc_env.core_fld) arcpy.JoinField_management(near_tbl, "NEAR_FID", corefc, "FID", cc_env.core_fld) # Limit pairings based on inputed Euclidean distances srow, srows = None, None euc_dist_fld = arcpy.AddFieldDelimiters(near_tbl, "NEAR_DIST") expression = (euc_dist_fld + " > " + str(cc_env.min_euc_dist)) srows = arcpy.SearchCursor(near_tbl, expression, "", jtocore_fn + "; NEAR_DIST", jtocore_fn + " A; NEAR_DIST A") # Process near table and output into a link table srow = srows.next() if srow: core_list.add(int(frm_core)) while srow: to_coreid = srow.getValue(jtocore_fn) dist_value = srow.getValue("NEAR_DIST") writer.writerow([i, frm_core, to_coreid, -1, -1, 1, dist_value, -1, -1, -1]) core_list.add(to_coreid) srow = srows.next() i += 1 except Exception: raise finally: cc_util.delete_features( [near_tbl, os.path.splitext(corefc)[0] + "_Pnt.shp"]) if link_tbl: link_tbl.close() if srow: del srow if srows: del srows return core_list
def cc_copy_inputs(): """Clip Climate Linkage Mapper inputs to smallest extent""" ext_poly = os.path.join(cc_env.out_dir, "ext_poly.shp") # Extent polygon try: lm_util.gprint("\nCOPYING LAYERS AND, IF NECESSARY, REDUCING EXTENT") if not arcpy.Exists(cc_env.inputs_gdb): arcpy.CreateFileGDB_management(os.path.dirname(cc_env.inputs_gdb), os.path.basename(cc_env.inputs_gdb)) 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 # Copying to gdb avoids gdal conflict later with ascii conversion 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) except Exception: raise finally: cc_util.delete_features(ext_poly)