Python+MRT 并行處理MODIS數(shù)據(jù)

最近涉及到MODIS 植被指數(shù)、地表溫度、蒸散等時序數(shù)據(jù)產(chǎn)品的處理桶良,因此對MODIS數(shù)據(jù)批處理的方法進行了改進。主要是想充分利用工作站的性能沮翔,提升數(shù)據(jù)處理的效率陨帆。雖然用了兩三天時間,但是”磨刀不誤砍柴工“采蚀,還是值得的疲牵。

批處理工具MRT

MODIS數(shù)據(jù)批處理大多是依靠MRT工具,通過執(zhí)行cmd命令的方式完成榆鼠,需要提前手動生成相關(guān)產(chǎn)品處理的prm文件纲爸,可參考:

https://blog.csdn.net/jingchenlin1996/article/details/88548728

如果不同年份和月份的數(shù)據(jù)存放在不同的目錄下,那么就涉及到了文件夾的遍歷妆够。我們選擇了 python 的os.walk()函數(shù)识啦,并通過os.popen()函數(shù)執(zhí)行批處理的cmd命令。

#! usr/bin/python
#coding=utf-8
# 運行此文件前需要先運行MRT生成prm配置文件

import os
def MRTBacth(fileInpath,fileOutpath,prmFilepath):
    for dirPath, dirNames, fileNames in os.walk(fileInpath):
        if len(fileNames)> 0:
            strCMD = 'cd .. && C: && cd C:/MRT/bin &&java -jar MRTBatch.jar -d ' + dirPath + \
                   ' -p prmFilepath -o ' + fileOutpath + '&&MRTBatch.bat'
            res = os.popen(strCMD)
            print(res.read())
            print(fileOutpath +':       Finished')
MRTBacth('H:/DATA/MOD16A2/2001')

到這里都只是簡單的單核計算神妹。

并行計算

python并行計算可參考資料:

https://www.cnblogs.com/fugeny/p/9898971.html

以及基礎(chǔ)的并發(fā)颓哮、并行、阻塞等概念鸵荠,參考:

https://www.cnblogs.com/zhangyafei/p/9606765.html

Python+MRT 并行處理

遇見的問題

我們選擇了multiprocessing的多進程包冕茅,在上面MRTBatch()函數(shù)的基礎(chǔ)上增加下面的內(nèi)容:

#導(dǎo)入multiprocessing包和functools包的partial模塊
import multiprocessing as mp
from functools import partial
#windows環(huán)境下主程序應(yīng)放在if __name__ =="__main__"下
if __name__ == "__main__":
    fileInpath = 'H:/DATA/MOD16A2/'
    fileOutpath='H:\DATA\RESULT\MOD16A2'
    prmFile='H:/DATA/MOD16A2.prm'
    #獲取輸入路徑下的所有包含文件的文件路徑
    fileList=GetFile(fileInpath)
    #創(chuàng)建10個進程的進程池,
    pool = mp.Pool(10)
    #因為MRTBactch()需要傳入多參數(shù)蛹找,可通過partial()函數(shù)固定其他參數(shù)
    func=partial(MRTBacth,fileOutpath=fileOutpath,prmFile=prmFile)
    #通過pool.map()函數(shù)實現(xiàn)并行計算
    res=pool.map(func,fileList)
    print(res.get())
    pool.close()
    pool.join()

看似沒什么問題姨伤,實際上計算的結(jié)果并不對。正常輸出的tif文件數(shù)據(jù)量約180M熄赡,但此時程序算出來的數(shù)據(jù)量約1.7G姜挺,差不多10輩的差距。更意外的是只生成了一個TmpMosaic.hdf 的中間過程文件彼硫。

1.7G的輸出結(jié)果炊豪,正常為180M

通過查看日志文件凌箕,發(fā)現(xiàn)雖然進程池中的進程都執(zhí)行了mrtmosaic.exe和resample.exe,但是這倆exe在不同進程中的輸入輸出路徑都是一樣的词渤。

輸入都是該路徑下的22個hdf牵舱,輸出也是同樣路徑的tmpMosaic.hdf

后來發(fā)現(xiàn)當(dāng)執(zhí)行MRT批處理中“java -jar MRTBatch.jar -d ' + dirPath + -p prmFilepath -o ' + fileOutpath ”的命令時,MRT會在其安裝目錄下生成文件名為MRTBatch.bat的文件缺虐,文件內(nèi)容如下(請忽略具體的輸出輸出路徑):

mrtmosaic -s "1 0 0 0 0" -i H:\DATA\RESULT\MOD16A2/2001\353\MOD16A2.A2001353_mosaic.prm -o H:\DATA\RESULT\MOD16A2/2001\353\TmpMosaic.hdf
resample -p H:\DATA\RESULT\MOD16A2/2001\353\MOD16A2.A2001353_resample.prm
del H:\DATA\RESULT\MOD16A2/2001\353\TmpMosaic.hdf

原來MRTBatch.bat的文件記錄的時后續(xù)調(diào)用mrtmosaic.exe和resample.exe所需的輸入?yún)?shù)芜壁。這解釋了為什么MRT批處理命令中要有”MRTBatch.bat“這一命令,這也解釋了為什么不同進程的輸出結(jié)果是相同的高氮。因為每個進程都會在同一目錄下生成MRTBatch.bat文件慧妄,文件會自動覆蓋,最終只記錄了最后一次的內(nèi)容剪芍。

解決辦法

改進的方法就是獨立調(diào)用mrtmosaic.exe和resample.exe塞淹。通過查看MRT幫助文檔,了解了兩個exe的參數(shù)罪裹,對程序進行了調(diào)試和修改饱普。最終的程序代碼如下:

#! usr/bin/python
#coding=utf-8
# 運行此文件前需要先運行MRT生成prm配置文件

import os,shutil,time,re
import multiprocessing as mp
from functools import partial

#文件夾遍歷,獲取包含hdf文件的所有文件夾状共,并以字符串列表返回
def GetFile(fileInpath):
   fileList=[]
   for dirPath, dirNames, fileNames in os.walk(fileInpath):
       if len(fileNames) > 0:
           fileList.append(dirPath)
   return fileList
#獲取某文件夾下所有后綴為hdf的文件名套耕,以字符串列表返回
def GetFileName(fileInpath,fileType):
   fileNames = os.listdir(fileInpath)
   fileNameArr = []
   for fileName in fileNames:
       if os.path.splitext(fileName)[1] == fileType:
           fileNameArr.append(fileName)
   return fileNameArr

#mrtmosaic.exe
def MrtmosaicPro(fileInpath,fileOutpath,SpectralSubset):
   #build mosaic prm file,which records all the datafiles under the fileInpath
   fileNames = GetFileName(fileInpath, '.hdf')
   prmName = fileOutpath + '/' + 'tmpMosaic.prm'
   for fileName in fileNames:
       with open(prmName, 'a+') as f:
           f.write(fileInpath+'/'+fileName + '\n')

   #get the product type and  DOY information
   productType=fileNames[0].split('.')[0]
   DOY=fileNames[0].split('.')[1]
   fileOutName=fileOutpath +'/'+productType+'.'+DOY+'.'+'TmpMosaic.hdf'
   #run mrtmosaic.exe
   strCMD = 'cd .. && C: && cd C:/MRT/bin && mrtmosaic -i '+prmName+ ' -s "'+SpectralSubset+'" -o '+fileOutName
   res = os.popen(strCMD)
   print(res.read())
   print(fileOutName +':       Finished')
   return fileOutName,prmName

#fileInpath:MOD16A2.A2010001.tmpmosaic.hdf
#fileOutpath:
#prmFilepath:
#SpectralSubset:'1 0 0 0 0'
def ResamplePro(fileInpath,fileOutpath,prmFilepath,SpectralSubset):
   #copy the prm file into fileoutpath and update it
   shutil.copy(prmFilepath,fileOutpath)
   filedata=[]
   newPrmFilepath=fileOutpath+'/'+os.path.basename(prmFilepath)
   fileOutName=os.path.basename(fileInpath).split('.')[0]+'.'+os.path.basename(fileInpath).split('.')[1]+'.tif'
   targetStr1='INPUT_FILENAME = '
   newStr1='INPUT_FILENAME = '+fileInpath
   targetStr2='SPECTRAL_SUBSET = '
   newStr2 = 'SPECTRAL_SUBSET = (' + str(SpectralSubset.count('1'))+')'
   targetStr3 = 'OUTPUT_FILENAME = '
   newStr3 = 'OUTPUT_FILENAME = ' + fileOutpath+'/'+fileOutName

   #read in the prmfile and replace the variables of input filename,SPECTRAL_SUBSET and OUTPUT_FILENAME
   with open(newPrmFilepath, "r") as file:
       #lines=file.read()
       for line in file:
           if re.match(targetStr1,line):
               line=newStr1
           if re.match(targetStr2,line):
               line=newStr2
           if re.match(targetStr3,line):
               line=newStr3
           filedata.append(line)

   with open(newPrmFilepath,'a+') as file:
       file.seek(0)
       file.truncate()
       for i in range(len(filedata)):
           file.write(filedata[i]+'\n')
   #run resample.exe
   strCMD = 'cd .. && C: && cd C:/MRT/bin && resample -p ' +newPrmFilepath
   res = os.popen(strCMD)
   print(res.read())
   print(fileOutName + ':       Finished')
   return newPrmFilepath

def MRTBacth(fileInpath,fileOutpath,prmFile,SpectralSubset):
   #根據(jù)實際情況自己改
   newFileOutpath=fileOutpath+fileInpath[15:24]
   if os.path.exists(newFileOutpath) == False:
       os.makedirs(newFileOutpath)

   result= MrtmosaicPro(fileInpath, newFileOutpath, SpectralSubset)
   #use the output from mrtmosaic.exe as the inputfile to resample.exe
   newPrmFilepath=ResamplePro(result[0], newFileOutpath, prmFile, SpectralSubset)
   #delete prm file and tmpmosaic.hdf
   strDelCMD='del ' + result[0] + '&& del ' + result[1]+'&& del '+newPrmFilepath
   res = os.popen(strDelCMD)

if __name__ == "__main__":
   startTime = time.time()
   fileInpath = 'H:/DATA/MOD16A2/'
   fileOutpath='H:\DATA\RESULT\MOD16A2'
   prmFile='H:/DATA/MOD16A2.prm'
   SpectralSubset="1 0 0 0 0"
   fileList=GetFile(fileInpath)

   #MRTBacth(fileList[0],fileOutpath,prmFile,SpectralSubset)
   # cores number
   cores = mp.cpu_count()
   pool = mp.Pool(int(cores * 2 / 3))

   func=partial(MRTBacth,fileOutpath=fileOutpath,prmFile=prmFile,SpectralSubset=SpectralSubset)
   res=pool.map(func,fileList)
   print(res.get())
   pool.close()
   pool.join()
   endTime = time.time()
   print("used time is ", endTime - startTime)

總結(jié)

以前使用MRT沒有注意到程序運行的一些細(xì)節(jié)峡继,通過這次實驗冯袍,了解了MRT內(nèi)部運行的機制。機器的內(nèi)存和顯卡資源還未利用起來鬓椭,后續(xù)將對程序進一步優(yōu)化和改進颠猴。最后放一張cpu的圖:


image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末关划,一起剝皮案震驚了整個濱河市小染,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贮折,老刑警劉巖裤翩,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異调榄,居然都是意外死亡踊赠,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門每庆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來筐带,“玉大人,你說我怎么就攤上這事缤灵÷准” “怎么了蓝晒?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長帖鸦。 經(jīng)常有香客問我芝薇,道長,這世上最難降的妖魔是什么作儿? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任洛二,我火速辦了婚禮,結(jié)果婚禮上攻锰,老公的妹妹穿的比我還像新娘晾嘶。我一直安慰自己,他們只是感情好娶吞,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布变擒。 她就那樣靜靜地躺著,像睡著了一般寝志。 火紅的嫁衣襯著肌膚如雪娇斑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天材部,我揣著相機與錄音毫缆,去河邊找鬼。 笑死乐导,一個胖子當(dāng)著我的面吹牛苦丁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播物臂,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼旺拉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了棵磷?” 一聲冷哼從身側(cè)響起蛾狗,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎仪媒,沒想到半個月后沉桌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡算吩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年留凭,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片偎巢。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蔼夜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出压昼,到底是詐尸還是另有隱情求冷,我是刑警寧澤翠订,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站遵倦,受9級特大地震影響尽超,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜梧躺,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一似谁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧掠哥,春花似錦巩踏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至禁舷,卻和暖如春彪杉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背牵咙。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工派近, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人洁桌。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓渴丸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親另凌。 傳聞我的和親對象是個殘疾皇子谱轨,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容