2016-04-25 73 views
2

我正在做一些數字運算與arcpy光柵並希望使用multiprocessing包來加快速度。基本上,我需要遍歷元組列表,使用每個元組進行一些柵格計算並將一些輸出寫入文件。我的輸入包括一個數據光柵(測深),限定區域的光柵,和兩個浮體(水錶面高度,深度)的元組的。我的程序由一個函數computeplane組成,它接收一個元組並運行一系列的柵格計算以生成五個柵格(總體,沿岸,表面,地下,深度),然後爲每個柵格調用函數processtable以將值寫入使用arcpy.sa.ZonalStatisticsAsTable DBF,添加使用arcpy.AddField_management一些領域,DBF轉換爲使用arcpy.TableToTable_conversion一個csv,最後刪除使用arcpy.Delete_management DBF文件。ArcPy中+多:錯誤:無法保存柵格數據集

基於一些other SO posts,我已經將我的代碼包裝在main()中,因此multiprocessing.Pool會被認爲很好玩。我用main()創建元組和pool.map做多。我使用tempfile包爲dbf文件選擇名稱以避免名稱衝突; csv文件名保證不與其他線程衝突。

我已經測試我的代碼與for循環,它工作正常,但是當我嘗試使用pool.map我得到

RuntimeError: ERROR 010240: Could not save raster dataset to C:\Users\Michael\AppData\Local\ESRI\Desktop10.4\SpatialAnalyst\lesst_ras with output format GRID.

這到底是怎麼回事?此錯誤不會在非多進程版本的代碼顯示出來,我不隨地---然後重新寫出來的柵格,我不知道該怎麼arcpy涉及中間柵格(我肯定不要」不要以爲它會讓他們記憶猶新---它們太大了)。我是否需要告訴arcpy有關處理多處理工作的光柵計算的方式?我已經在下面包含了我的python文件。

import arcpy 
arcpy.CheckOutExtension("Spatial") 
import arcpy.sa 
import numpy 
import multiprocessing 
import tempfile 
bathymetry_path = r'C:/GIS workspace/RRE/habitat.gdb/bathymetry_NGVD_meters' 
zones_path = r'C:/GIS workspace/RRE/habitat.gdb/markerzones_meters' 
table_folder = r'C:/GIS workspace/RRE/zonetables' 
bathymetry = arcpy.sa.Raster(bathymetry_path) 
zones = arcpy.sa.Raster(zones_path) 

def processtable(raster_obj, zone_file, w, z, out_folder, out_file): 
    temp_name = "/" + next(tempfile._get_candidate_names()) + ".dbf" 
    arcpy.sa.ZonalStatisticsAsTable(zone_file, 'VALUE', raster_obj, out_folder + temp_name, "DATA", "SUM") 
    arcpy.AddField_management(out_folder + temp_name, "wse", 'TEXT') 
    arcpy.AddField_management(out_folder + temp_name, "z", 'TEXT') 
    arcpy.CalculateField_management(out_folder + temp_name, "wse", "'" + str(w) + "'", "PYTHON") 
    arcpy.CalculateField_management(out_folder + temp_name, "z", "'" + str(z) + "'", "PYTHON") 
    arcpy.TableToTable_conversion(out_folder + temp_name, out_folder, out_file) 
    arcpy.Delete_management(out_folder + temp_name) 

def computeplane(wsedepth): 
    wse = wsedepth[0] 
    depth = wsedepth[1] 
    total = bathymetry < depth 
    littoral = total & ((wse - bathymetry) < 2) 
    surface = total & ~(littoral) & ((total + wse - depth) < (total + 2)) 
    profundal = total & ((total + wse - depth) > (total + 5)) 
    subsurface = total & ~(profundal | surface | littoral) 
    # zonal statistics table names 
    total_name = 'total_w' + str(wse) + '_z' + str(depth) + '.csv' 
    littoral_name = 'littoral_w' + str(wse) + '_z' + str(depth) + '.csv' 
    surface_name = 'surface_w' + str(wse) + '_z' + str(depth) + '.csv' 
    subsurface_name = 'subsurface_w' + str(wse) + '_z' + str(depth) + '.csv' 
    profundal_name = 'profundal_w' + str(wse) + '_z' + str(depth) + '.csv' 
    # compute zonal statistics 
    processtable(total, zones, wse, depth, table_folder, total_name) 
    processtable(littoral, zones, wse, depth, table_folder, littoral_name) 
    processtable(surface, zones, wse, depth, table_folder, surface_name) 
    processtable(profundal, zones, wse, depth, table_folder, profundal_name) 
    processtable(subsurface, zones, wse, depth, table_folder, subsurface_name) 

def main(): 
    watersurface = numpy.arange(-15.8, 2.7, 0.1) 
    # take small subset of the tuples: watersurface[33:34] 
    wsedepths = [(watersurface[x], watersurface[y]) for x in range(watersurface.size)[33:34] for y in range(watersurface[0:x+1].size)] 
    pool = multiprocessing.Pool() 
    pool.map(computeplane, wsedepths) 
    pool.close() 
    pool.join() 

if __name__ == '__main__': 
    main() 

UPDATE

一些更多的偵探發現,這與其說是一個multiprocessing問題,與ArcGIS中確實光柵處理方式的問題。柵格代數結果寫入默認工作區中的文件;在我的情況下,我沒有指定一個文件夾,所以arcpy正在寫入一些AppData文件夾的柵格。基於您的代數表達式,ArcGIS使用基本名稱,如Lessth,Lessth_1等。由於我沒有指定工作區,所有multiprocessing線程正在寫入此文件夾。雖然單個arcpy過程可以跟蹤的名字,多進程都儘量寫同樣的光柵名並撞到其他進程的鎖。

我試圖創建在computeplane開始隨機工作區(文件GDB),然後在年底將其刪除,但arcpy通常不及時和DELETE語句的過程中死機釋放鎖。所以我不知道如何繼續。

回答

1

那麼,ERROR 010240的解決方案是使用arcpy.gp.RasterCalculator_sa函數而不是arcpy.sa來編寫具有指定輸出名稱的柵格。不幸的是,在重新實施後,我碰到了

FATAL ERROR (INFADI) MISSING DIRECTORY

它被描述爲in another stackexchange post。那篇文章中的建議是在每個函數調用中指定一個不同的工作區,這是我嘗試的第一件事(沒有成功)。還有一些討論一次只能寫出一個光柵,所以無論如何多處理光柵計算都沒有意義。我放棄!

相關問題