I am batch processing a large amount of distance functions (~50,000) using ArcGIS 9.3. In this version, using spatial analyst functions, it seems to be the case that users cannot parallelize processes across cores, or write to in_memory instead of the hard disk for intermediate steps, and there's a memory leak inherent in the program that causes processing to slow down over multiple loops. I've seen a forum post that shows a crude workaround for the memory leak that just turns off garbage collection, but that alone probably won't help a whole lot. Right now I'm looking at processing times on the order of a few weeks on the computer I'm using for this.
Does anyone know of any reliable work-arounds that would allow me to write SA output to in_memory, parallelize processes, or in some other way significantly speed up processing? I'm open to using ERDAS if I have to.
Script:
# Import system modules
import sys, string, os, arcgisscripting, time, shutil
# Create the Geoprocessor object
gp = arcgisscripting.create(9.3)
# Allow overwrites
gp.overwriteoutput = 1
# ----------------------------------------------------------
# Set changeable model parameters
# ----------------------------------------------------------
cell_sz = 90.04245658
Max_oid = 1 # Should be = 54567 for irrigated agriculture, in province sources - Range function starts at 0 and stops 1 before number in range - so this number should be = number of records in shapefile
Win_sz = 3100 # This is the minimum possible size, and should make it so that even the largest k results in values = 0.001 or less at boundary
# Create a folder for this set of runs, designated by the current time, then copy the script being run to the folder and time stamp it
t = time.localtime()
timeholder = str(t[0]) + '_' + str(t[1]) + '_' + str(t[2]) + '_' + str(t[3]) + str(t[4]) + '_' + str(t[5])
folder_time_name = "M:\\Jess_GIS_NIDR\\" + timeholder
os.mkdir(folder_time_name)
filename=sys._getframe().f_code.co_filename
shutil.copyfile(filename, folder_time_name + '\\this_script_executed_' + timeholder + '.py') #shutil
# Check out any necessary licenses
gp.CheckOutExtension("spatial")
cell_sz_str = str(cell_sz) + " METERS"
gp.cellSize = cell_sz
# Set up loop to go through the data set, iteratively select cells out, and processs distance calculations
for i in range(Max_oid):
pt = i
print "Processing point number " + str(pt)
# Load prepped dataset containing this point
irragg = "M:\\Jess_GIS_NIDR\\Pts_irragg\\pt_int_" + str(pt) + ".shp"
# Publish output to common folders - may add additional dists_proc style folders
Dists_raw = "in_memory\\dists_raw"
# Define local variables (files only associated with processing this source cell)
DEM = "M:\\Jess_GIS_NIDR\\InputRasters_Globcover_Hydrosheds\\HydroSHEDS\\dem"
Dir_hydro = "M:\\Jess_GIS_NIDR\\InputRasters_Globcover_Hydrosheds\\HydroSHEDS\\drain_dir"
Dists_fin = folder_time_name + "\\Dists\\Dists_fin.shp"
# Identify and set processing extent
y = []
x = []
cur = gp.SearchCursor(irragg)
row = cur.Next()
while row:
extent = row.Shape.Extent
y.append(extent.ymin)
x.append(extent.xmin)
row = cur.Next()
del row
del cur
ypt = y.pop(0)
xpt = x.pop(0)
def incmax(a): return (a + Win_sz)
def incmin(b): return (b - Win_sz)
ymin = incmin(ypt)
ymax = incmax(ypt)
xmin = incmin(xpt)
xmax = incmax(xpt)
del y
del x
gp.extent = "%f %f %f %f" % (xmin, ymin, xmax, ymax)
# Path-distance function
gp.PathDistance_sa(irragg, Dists_raw, "", DEM, Dir_hydro, "FORWARD 0.01 0.5", "", "", "", "")
# Convert distance results to permanent shape file
gp.RasterToPoint_conversion(Dists_raw, Dists_fin, "VALUE")
# Further processing of original distance raster to get at first order ideas of distance
# ---------------------------------------------------------------------------------------
# Crudely correct for the fact that the original land-use data was originally at a coarser resolution than this dataset
gp.AddField_management(Dists_fin, "Dcorr", "DOUBLE", "", "", "", "", "NULLABLE", "", "")
gp.CalculateField_management(Dists_fin, "Dcorr", "[RASTERVALU] - 90.04245658", "", "")
# First order distance function
gp.AddField_management(Dists_fin, "Dist_k", "DOUBLE", "", "", "", "", "NULLABLE", "", "")
gp.CalculateField_management(Dists_fin, "Dist_k", "Exp([Dcorr]*-0.00231)", "", "")