I need some assistance to figure out if the following is a bug, if so what work around can I use. I've written a Python Script I need to change the Processing Extent for each feature layer being processed. I obtain the extent for each feature layer using the following Python code:
process_extent = arcpy.Describe(site_buffer).extent
If I print process_extent , the results are what I would expect:
I then try to set the Processing Extent using the process_extent as input based on the following code:
arcpy.env.extent = process_extent
if I print arcpy.env.extent, the results are not what I would expect:
Solved! Go to Solution.
Hi Xander
I figured out a workaround using ArcPy.da.SearchCursor:
''' Created on Aug 3, 2015 Calculate the time to traverse a terrain based on Toblers Hiking Function based on slope @author: PeterW ''' # import system modules and site packages import os import time import arcpy from arcpy.sa import * from difflib import Match # process time Function def hms_string(sec_elapsed): h = int(sec_elapsed / (60 * 60)) m = int((sec_elapsed % (60 * 60)) / 60) s = sec_elapsed % 60 return "{}h:{:>02}m:{:>05.2f}s".format(h, m, s) # processing start time start_time = time.time() # set environment settings arcpy.env.overwriteOutput = True # check out extensions arcpy.CheckOutExtension("Spatial") # set input and output workspace inws = r"F:\Projects\2015\G111741\Model01\Rasters" fgdb = r"F:\Projects\2015\G111741\Model01\Model01.gdb" # calculate the slope in degrees inras = os.path.join(inws, "raw2") out_measurement = "DEGREE" slope_deg = Slope(inras, out_measurement) # spatial reference for output results coordsys = arcpy.Describe(inras).spatialReference # set site locations and input Toblers Hiking Function Vertical factor sites = os.path.join(fgdb, "Schools_All") sites_buffer = os.path.join(fgdb, "Schools_Buffer") vertical_factor = arcpy.sa.VfTable(os.path.join(inws, "ToblerAway.txt")) #@UndefinedVariable # create output feature class to store walk time polylines for each site_buffer walk_poly = os.path.join(fgdb, "walk_poly") # check if walk_poly exists else create it from scratch if arcpy.Exists(walk_poly): arcpy.Delete_management(walk_poly) arcpy.CreateFeatureclass_management(fgdb, "walk_poly", "POLYLINE", "", "", "", coordsys, "", "", "", "") arcpy.AddField_management(walk_poly, "Name", "TEXT", "", "", 25, "", "", "", "") arcpy.AddField_management(walk_poly, "Contour", "SHORT", "", "", "", "", "", "", "") else: arcpy.CreateFeatureclass_management(fgdb, "walk_poly", "POLYLINE", "", "", "", coordsys, "", "", "", "") arcpy.AddField_management(walk_poly, "Name", "TEXT", "", "", 25, "", "", "", "") arcpy.AddField_management(walk_poly, "Contour", "SHORT", "", "", "", "", "", "", "") # walk distance\time (1km = 12min; 2km = 24min; 2.5km = 30min; 5km = 60min) walk_int = [12, 24, 30, 60] # create 5km buffers for each site to be used as processing extent sites_buffer = os.path.join("in_memory", "sites_buffer") arcpy.Buffer_analysis(sites, sites_buffer, "5 Kilometers") with arcpy.da.SearchCursor(sites_buffer, ["OBJECTID", "NAME", "SHAPE@"]) as scur1: #@UndefinedVariable for row1 in scur1: with arcpy.da.SearchCursor(sites, ["OBJECTID", "NAME", "SHAPE@"]) as scur2: #@UndefinedVariable count = 0 for row2 in scur2: count += 1 if row1[1] == row2[1]: # processing start time start_time = time.time() process_extent = row1[2].extent arcpy.env.extent = process_extent site_name = row2[1].replace(" ","_").replace("-","_").replace("(","").replace(")","") sql_exp1 = "Name = '{}'".format(row2[1]) site_lyr = site_name arcpy.MakeFeatureLayer_management(sites, site_lyr, sql_exp1) cost = PathDistance(site_lyr, slope_deg, "", "", "", inras, vertical_factor, "","") print("Processing {} Cost Raster").format(site_name) costmin = Times(cost, 60) print("Processing {} Cost per Minute Raster").format(site_name) walk_name = "walk_cont" + "_" + str(count) walk_cont = os.path.join("in_memory", walk_name) print("Processing & Sorting {} Walk Contours").format(site_name) ContourList(costmin, walk_cont, walk_int) walk_name2 = walk_name + "_" + "sorted" walk_sorted = os.path.join("in_memory", walk_name2) arcpy.Sort_management(walk_cont, walk_sorted, [["Contour", "ASCENDING"]], "") arcpy.AddField_management(walk_sorted, "Name", "TEXT", "", "", 50, "", "", "", "") sql_exp2 = "'{}'".format(row2[1]) arcpy.CalculateField_management(walk_sorted, "Name", sql_exp2, "PYTHON_9.3") with arcpy.da.SearchCursor(walk_sorted, ["SHAPE@", "Name", "Contour"]) as scur: #@UndefinedVariable with arcpy.da.InsertCursor(walk_poly, ["SHAPE@", "Name", "Contour"]) as icur: #@UndefinedVariable for srow in scur: icur.insertRow(srow) # Processing end time end_time = time.time() print "It took {} to execute {}".format(hms_string(end_time - start_time),site_name) print ("Completed Processing All Sites") # check in extensions arcpy.CheckInExtension("Spatial") # processing end time end_time = time.time() print "It took {} to execute this".format(hms_string(end_time - start_time))
I should mention that I'm using ArcGIS 10.2.2 with Python 2.7.6
Regards
Peter Wilson
That indeed looks like a bug. I just did a test looping through all the featureclasses in a File Geodatabase with version 10.3 I have here and there is no difference between the extent read from the fc and after the extent is set to the env.extent. When the "1,#QNAN 1,#QNAN 1,#QNAN 1,#QNAN NaN NaN NaN NaN" occurs it is already in the input featureclass extent.
Could you show the rest of the code to see if something else is happening with the extent?
Hi Xander
The full Python code is attached below:
''' Created on Jul 16, 2015 Calculate the time to traverse a terrain based on Toblers Hiking Function based on slope @author: PeterW ''' # import system modules and site packages import os import arcpy from arcpy.sa import * import time def hms_string(sec_elapsed): h = int(sec_elapsed / (60 * 60)) m = int((sec_elapsed % (60 * 60)) / 60) s = sec_elapsed % 60 return "{}h:{:>02}m:{:>05.2f}s".format(h, m, s) # End hms_string start_time = time.time() # set environment settings arcpy.env.overwriteOutput = True # check out extensions arcpy.CheckOutExtension("Spatial") # set input and output workspace inws = r"F:\Projects\2015\G111741\Model01\Rasters" fgdb = r"F:\Projects\2015\G111741\Model01\Model01.gdb" arcpy.env.workspace = inws # calculate the slope in degrees inras = "raw2" out_measurement = "DEGREE" slope_deg = Slope(inras, out_measurement) # spatial reference for output results coordsys = arcpy.Describe(inras).spatialReference # set site locations and input Tobler Hiking Function Vertical Factor sites = os.path.join(fgdb,"Schools_All2") vertical_factor = arcpy.sa.VfTable(os.path.join(inws, "ToblerAway.txt")) #@UndefinedVariable # create output feature class to store walk time polylines for each site walk_poly = os.path.join(fgdb, "walk_poly") # check if walk_poly exists else create it from scratch if arcpy.Exists(walk_poly): arcpy.Delete_management(walk_poly) arcpy.CreateFeatureclass_management(fgdb, "walk_poly", "POLYLINE", "", "", "", coordsys, "", "", "", "") arcpy.AddField_management(walk_poly, "Name", "TEXT", "", "", 25, "", "", "", "") arcpy.AddField_management(walk_poly, "Contour", "SHORT", "", "", "", "", "", "", "") else: arcpy.CreateFeatureclass_management(fgdb, "walk_poly", "POLYLINE", "", "", "", coordsys, "", "", "", "") arcpy.AddField_management(walk_poly, "Name", "TEXT", "", "", 25, "", "", "", "") arcpy.AddField_management(walk_poly, "Contour", "SHORT", "", "", "", "", "", "", "") # walking distance\time (1km = 12min; 2km = 24min; 2.5km = 30min; 5km = 60min) walk_int = [12, 24, 30, 60] with arcpy.da.SearchCursor(sites, ["NAME"]) as cursor: #@UndefinedVariable count = 0 for row in cursor: count += 1 site_name = row[0].replace(" ","_").replace("-","_").replace("(","").replace(")","") # remove non valid characters sql_exp1 = "Name = '{}'".format(row[0]) site_lyr = site_name arcpy.MakeFeatureLayer_management(sites, site_lyr, sql_exp1) # create feature layer for each site site_buffer = os.path.join("in_memory", site_name) arcpy.Buffer_analysis(site_lyr, site_buffer, "5 Kilometers") # create 5 kilometer buffer for each site process_extent = arcpy.Describe(site_buffer).extent # set processing extent to 5 kilometer buffer of site arcpy.env.extent = process_extent # set processing extent to site buffer for each site location cost = PathDistance(site_lyr, slope_deg, "","","",inras, vertical_factor,"","") print ("Processing {} Cost Raster").format(site_name) costmin = Times(cost, 60) print ("Processing {} Cost per Minute Raster").format(site_name) walk_name = "walk_cont" + "_" + str(count) walk_cont = os.path.join("in_memory", walk_name) # save to in_memory print ("Processing & Sorting {} Walk Contours").format(site_name) ContourList(costmin, walk_cont, walk_int) walk_name2 = walk_name + "_" + "sorted" walk_sorted = os.path.join("in_memory", walk_name2) arcpy.Sort_management(walk_cont, walk_sorted, [["Contour", "ASCENDING"]],"") arcpy.AddField_management(walk_sorted, "Name", "TEXT", "", "", 50, "", "", "", "") sql_exp2 = "'{}'".format(row[0]) arcpy.CalculateField_management(walk_sorted, "Name", sql_exp2, "PYTHON_9.3") with arcpy.da.SearchCursor(walk_sorted,["SHAPE@", "Name", "Contour"]) as scur: #@UndefinedVariable with arcpy.da.InsertCursor(walk_poly, ["SHAPE@", "Name", "Contour"]) as icur: #@UndefinedVariable for srow in scur: icur.insertRow(srow) print ("Completed Processing All Sites") # check in extensions arcpy.CheckInExtension("Spatial") end_time = time.time() print "It took {} to execute this".format(hms_string(end_time - start_time))
Hi Xander
I figured out a workaround using ArcPy.da.SearchCursor:
''' Created on Aug 3, 2015 Calculate the time to traverse a terrain based on Toblers Hiking Function based on slope @author: PeterW ''' # import system modules and site packages import os import time import arcpy from arcpy.sa import * from difflib import Match # process time Function def hms_string(sec_elapsed): h = int(sec_elapsed / (60 * 60)) m = int((sec_elapsed % (60 * 60)) / 60) s = sec_elapsed % 60 return "{}h:{:>02}m:{:>05.2f}s".format(h, m, s) # processing start time start_time = time.time() # set environment settings arcpy.env.overwriteOutput = True # check out extensions arcpy.CheckOutExtension("Spatial") # set input and output workspace inws = r"F:\Projects\2015\G111741\Model01\Rasters" fgdb = r"F:\Projects\2015\G111741\Model01\Model01.gdb" # calculate the slope in degrees inras = os.path.join(inws, "raw2") out_measurement = "DEGREE" slope_deg = Slope(inras, out_measurement) # spatial reference for output results coordsys = arcpy.Describe(inras).spatialReference # set site locations and input Toblers Hiking Function Vertical factor sites = os.path.join(fgdb, "Schools_All") sites_buffer = os.path.join(fgdb, "Schools_Buffer") vertical_factor = arcpy.sa.VfTable(os.path.join(inws, "ToblerAway.txt")) #@UndefinedVariable # create output feature class to store walk time polylines for each site_buffer walk_poly = os.path.join(fgdb, "walk_poly") # check if walk_poly exists else create it from scratch if arcpy.Exists(walk_poly): arcpy.Delete_management(walk_poly) arcpy.CreateFeatureclass_management(fgdb, "walk_poly", "POLYLINE", "", "", "", coordsys, "", "", "", "") arcpy.AddField_management(walk_poly, "Name", "TEXT", "", "", 25, "", "", "", "") arcpy.AddField_management(walk_poly, "Contour", "SHORT", "", "", "", "", "", "", "") else: arcpy.CreateFeatureclass_management(fgdb, "walk_poly", "POLYLINE", "", "", "", coordsys, "", "", "", "") arcpy.AddField_management(walk_poly, "Name", "TEXT", "", "", 25, "", "", "", "") arcpy.AddField_management(walk_poly, "Contour", "SHORT", "", "", "", "", "", "", "") # walk distance\time (1km = 12min; 2km = 24min; 2.5km = 30min; 5km = 60min) walk_int = [12, 24, 30, 60] # create 5km buffers for each site to be used as processing extent sites_buffer = os.path.join("in_memory", "sites_buffer") arcpy.Buffer_analysis(sites, sites_buffer, "5 Kilometers") with arcpy.da.SearchCursor(sites_buffer, ["OBJECTID", "NAME", "SHAPE@"]) as scur1: #@UndefinedVariable for row1 in scur1: with arcpy.da.SearchCursor(sites, ["OBJECTID", "NAME", "SHAPE@"]) as scur2: #@UndefinedVariable count = 0 for row2 in scur2: count += 1 if row1[1] == row2[1]: # processing start time start_time = time.time() process_extent = row1[2].extent arcpy.env.extent = process_extent site_name = row2[1].replace(" ","_").replace("-","_").replace("(","").replace(")","") sql_exp1 = "Name = '{}'".format(row2[1]) site_lyr = site_name arcpy.MakeFeatureLayer_management(sites, site_lyr, sql_exp1) cost = PathDistance(site_lyr, slope_deg, "", "", "", inras, vertical_factor, "","") print("Processing {} Cost Raster").format(site_name) costmin = Times(cost, 60) print("Processing {} Cost per Minute Raster").format(site_name) walk_name = "walk_cont" + "_" + str(count) walk_cont = os.path.join("in_memory", walk_name) print("Processing & Sorting {} Walk Contours").format(site_name) ContourList(costmin, walk_cont, walk_int) walk_name2 = walk_name + "_" + "sorted" walk_sorted = os.path.join("in_memory", walk_name2) arcpy.Sort_management(walk_cont, walk_sorted, [["Contour", "ASCENDING"]], "") arcpy.AddField_management(walk_sorted, "Name", "TEXT", "", "", 50, "", "", "", "") sql_exp2 = "'{}'".format(row2[1]) arcpy.CalculateField_management(walk_sorted, "Name", sql_exp2, "PYTHON_9.3") with arcpy.da.SearchCursor(walk_sorted, ["SHAPE@", "Name", "Contour"]) as scur: #@UndefinedVariable with arcpy.da.InsertCursor(walk_poly, ["SHAPE@", "Name", "Contour"]) as icur: #@UndefinedVariable for srow in scur: icur.insertRow(srow) # Processing end time end_time = time.time() print "It took {} to execute {}".format(hms_string(end_time - start_time),site_name) print ("Completed Processing All Sites") # check in extensions arcpy.CheckInExtension("Spatial") # processing end time end_time = time.time() print "It took {} to execute this".format(hms_string(end_time - start_time))
Glad you resolved your problem. For speed considerations you may want to consider creating two dictionaries rather than using a nested cursor.
Peter,
Your code really helped me with a problem I was having! For anyone that can't be bothered to do a CTRL + F, look for Lines 66 & 67.
From the 10.3 help (since I don't know if 10.2 is fixed)
http://desktop.arcgis.com/en/desktop/latest/tools/environments/output-extent.htm
The extent entered is assumed to be in the coordinate system in which the input data is stored, even if the Output Coordinate System environment is set. If the tool takes multiple input datasets, the first dataset defines the coordinate system of the extent
So technically, it should be reset if you reset it each time.
HI Dan
Thanks for the reply, the coordinate systems are indeed the same.
Regards