Skip to content

Commit 0b1a67b

Browse files
committed
[processing] TauDEM provider overhaul
- add new TauDEM 5.1.2/5.2 tools: Gage watershed, TWI and Select GT Threshold - implement support for multifile TauDEM version - allow to use single- and multifile versions simultaneously Work done for Faunalia (http://faunalia.eu) (cherry-picked from 427adf7)
1 parent e1b08fb commit 0b1a67b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1432
-38
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
FILE(GLOB PY_FILES *.py)
2-
FILE(GLOB DESCR_FILES description/*.txt)
2+
FILE(GLOB SINGLE_DESCR_FILES description/single/*.txt)
3+
FILE(GLOB MULTI_DESCR_FILES description/multi/*.txt)
34

45
PLUGIN_INSTALL(processing algs/taudem ${PY_FILES})
5-
PLUGIN_INSTALL(processing algs/taudem/description ${DESCR_FILES})
6+
PLUGIN_INSTALL(processing algs/taudem/description/single ${SINGLE_DESCR_FILES})
7+
PLUGIN_INSTALL(processing algs/taudem/description/multi ${MULTI_DESCR_FILES})

python/plugins/processing/algs/taudem/TauDEMAlgorithm.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,21 @@
2727

2828
import os
2929
from PyQt4.QtGui import QIcon
30+
3031
from processing.core.GeoAlgorithm import GeoAlgorithm
3132
from processing.core.ProcessingLog import ProcessingLog
3233
from processing.core.ProcessingConfig import ProcessingConfig
3334
from processing.core.GeoAlgorithmExecutionException import \
3435
GeoAlgorithmExecutionException
35-
from processing.core.parameters import getParameterFromString
36+
3637
from processing.core.parameters import ParameterRaster
3738
from processing.core.parameters import ParameterVector
3839
from processing.core.parameters import ParameterBoolean
3940
from processing.core.parameters import ParameterString
4041
from processing.core.parameters import ParameterNumber
42+
from processing.core.parameters import getParameterFromString
4143
from processing.core.outputs import getOutputFromString
44+
4245
from TauDEMUtils import TauDEMUtils
4346

4447

python/plugins/processing/algs/taudem/TauDEMAlgorithmProvider.py

+82-31
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@
3030
from PyQt4.QtGui import QIcon
3131

3232
from processing.core.AlgorithmProvider import AlgorithmProvider
33-
from processing.core.ProcessingConfig import ProcessingConfig
34-
from processing.core.ProcessingConfig import Setting
33+
from processing.core.ProcessingConfig import ProcessingConfig, Setting
3534
from processing.core.ProcessingLog import ProcessingLog
35+
3636
from TauDEMAlgorithm import TauDEMAlgorithm
37+
from TauDEMMultifileAlgorithm import TauDEMMultifileAlgorithm
3738
from TauDEMUtils import TauDEMUtils
39+
3840
from peukerdouglas import PeukerDouglas
3941
from slopearea import SlopeArea
4042
from lengtharea import LengthArea
@@ -45,13 +47,22 @@
4547
from dinftranslimaccum import DinfTransLimAccum
4648
from dinftranslimaccum2 import DinfTransLimAccum2
4749

50+
from peukerdouglas_multi import PeukerDouglasMulti
51+
from slopearea_multi import SlopeAreaMulti
52+
from lengtharea_multi import LengthAreaMulti
53+
from dropanalysis_multi import DropAnalysisMulti
54+
from dinfdistdown_multi import DinfDistDownMulti
55+
from dinfdistup_multi import DinfDistUpMulti
56+
from gridnet_multi import GridNetMulti
57+
from dinftranslimaccum_multi import DinfTransLimAccumMulti
58+
from dinftranslimaccum2_multi import DinfTransLimAccum2Multi
59+
4860

4961
class TauDEMAlgorithmProvider(AlgorithmProvider):
5062

5163
def __init__(self):
5264
AlgorithmProvider.__init__(self)
5365
self.activate = False
54-
self.createAlgsList()
5566

5667
def getDescription(self):
5768
return self.tr('TauDEM (hydrologic analysis)')
@@ -64,10 +75,21 @@ def getIcon(self):
6475

6576
def initializeSettings(self):
6677
AlgorithmProvider.initializeSettings(self)
78+
6779
ProcessingConfig.addSetting(Setting(self.getDescription(),
6880
TauDEMUtils.TAUDEM_FOLDER,
6981
self.tr('TauDEM command line tools folder'),
7082
TauDEMUtils.taudemPath()))
83+
ProcessingConfig.addSetting(Setting(self.getDescription(),
84+
TauDEMUtils.TAUDEM_MULTIFILE_FOLDER,
85+
self.tr('TauDEM multifile command line tools folder'),
86+
TauDEMUtils.taudemMultifilePath()))
87+
ProcessingConfig.addSetting(Setting(self.getDescription(),
88+
TauDEMUtils.TAUDEM_USE_SINGLEFILE,
89+
self.tr('Enable singlefile TauDEM tools'), True))
90+
ProcessingConfig.addSetting(Setting(self.getDescription(),
91+
TauDEMUtils.TAUDEM_USE_MULTIFILE,
92+
self.tr('Enable multifile TauDEM tools'), False))
7193
ProcessingConfig.addSetting(Setting(self.getDescription(),
7294
TauDEMUtils.MPIEXEC_FOLDER,
7395
self.tr('MPICH2/OpenMPI bin directory'),
@@ -78,36 +100,65 @@ def initializeSettings(self):
78100

79101
def unload(self):
80102
AlgorithmProvider.unload(self)
103+
81104
ProcessingConfig.removeSetting(TauDEMUtils.TAUDEM_FOLDER)
105+
ProcessingConfig.removeSetting(TauDEMUtils.TAUDEM_MULTIFILE_FOLDER)
106+
ProcessingConfig.removeSetting(TauDEMUtils.TAUDEM_USE_SINGLEFILE)
107+
ProcessingConfig.removeSetting(TauDEMUtils.TAUDEM_USE_MULTIFILE)
82108
ProcessingConfig.removeSetting(TauDEMUtils.MPIEXEC_FOLDER)
83109
ProcessingConfig.removeSetting(TauDEMUtils.MPI_PROCESSES)
84110

85111
def _loadAlgorithms(self):
86-
self.algs = self.preloadedAlgs
87-
88-
def createAlgsList(self):
89-
self.preloadedAlgs = []
90-
folder = TauDEMUtils.taudemDescriptionPath()
91-
for descriptionFile in os.listdir(folder):
92-
if descriptionFile.endswith('txt'):
93-
try:
94-
alg = TauDEMAlgorithm(os.path.join(folder,
95-
descriptionFile))
96-
if alg.name.strip() != '':
97-
self.preloadedAlgs.append(alg)
98-
else:
99-
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
100-
self.tr('Could not open TauDEM algorithm: %s' % descriptionFile))
101-
except Exception, e:
102-
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
103-
self.tr('Could not open TauDEM algorithm: %s' % descriptionFile))
104-
105-
self.preloadedAlgs.append(PeukerDouglas())
106-
self.preloadedAlgs.append(SlopeArea())
107-
self.preloadedAlgs.append(LengthArea())
108-
self.preloadedAlgs.append(DropAnalysis())
109-
self.preloadedAlgs.append(DinfDistDown())
110-
self.preloadedAlgs.append(DinfDistUp())
111-
self.preloadedAlgs.append(GridNet())
112-
self.preloadedAlgs.append(DinfTransLimAccum())
113-
self.preloadedAlgs.append(DinfTransLimAccum2())
112+
self.algs = []
113+
basePath = TauDEMUtils.taudemDescriptionPath()
114+
115+
if ProcessingConfig.getSetting(TauDEMUtils.TAUDEM_USE_SINGLEFILE):
116+
folder = os.path.join(basePath, 'single')
117+
118+
for descriptionFile in os.listdir(folder):
119+
if descriptionFile.endswith('txt'):
120+
descriptionFile = os.path.join(folder, descriptionFile)
121+
self._algFromDescription(descriptionFile)
122+
123+
self.algs.append(PeukerDouglas())
124+
self.algs.append(SlopeArea())
125+
self.algs.append(LengthArea())
126+
self.algs.append(DropAnalysis())
127+
self.algs.append(DinfDistDown())
128+
self.algs.append(DinfDistUp())
129+
self.algs.append(GridNet())
130+
self.algs.append(DinfTransLimAccum())
131+
self.algs.append(DinfTransLimAccum2())
132+
133+
if ProcessingConfig.getSetting(TauDEMUtils.TAUDEM_USE_MULTIFILE):
134+
folder = os.path.join(basePath, 'multi')
135+
136+
for descriptionFile in os.listdir(folder):
137+
if descriptionFile.endswith('txt'):
138+
descriptionFile = os.path.join(folder, descriptionFile)
139+
self._algFromDescription(descriptionFile, True)
140+
141+
self.algs.append(PeukerDouglasMulti())
142+
self.algs.append(SlopeAreaMulti())
143+
self.algs.append(LengthAreaMulti())
144+
self.algs.append(DropAnalysisMulti())
145+
self.algs.append(DinfDistDownMulti())
146+
self.algs.append(DinfDistUpMulti())
147+
self.algs.append(GridNetMulti())
148+
self.algs.append(DinfTransLimAccumMulti())
149+
self.algs.append(DinfTransLimAccum2Multi())
150+
151+
def _algFromDescription(self, descriptionFile, multifile=False):
152+
try:
153+
if multifile:
154+
alg = TauDEMMultifileAlgorithm(descriptionFile)
155+
else:
156+
alg = TauDEMAlgorithm(descriptionFile)
157+
if alg.name.strip() != '':
158+
self.algs.append(alg)
159+
else:
160+
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
161+
self.tr('Could not open TauDEM algorithm: %s' % descriptionFile))
162+
except Exception, e:
163+
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
164+
self.tr('Could not open TauDEM algorithm %s:\n%s' % (descriptionFile, str(e))))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
TauDEMMultifileAlgorithm.py
6+
---------------------
7+
Date : March 2015
8+
Copyright : (C) 2012 by Alexander Bruy
9+
Email : alexander dot bruy at gmail dot com
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
__author__ = 'Alexander Bruy'
21+
__date__ = 'March 2015'
22+
__copyright__ = '(C) 2015, Alexander Bruy'
23+
24+
# This will get replaced with a git SHA1 when you do a git archive
25+
26+
__revision__ = '$Format:%H$'
27+
28+
import os
29+
from PyQt4.QtGui import QIcon
30+
31+
from processing.core.GeoAlgorithm import GeoAlgorithm
32+
from processing.core.ProcessingLog import ProcessingLog
33+
from processing.core.ProcessingConfig import ProcessingConfig
34+
from processing.core.GeoAlgorithmExecutionException import \
35+
GeoAlgorithmExecutionException
36+
37+
from processing.core.parameters import ParameterFile
38+
from processing.core.parameters import ParameterVector
39+
from processing.core.parameters import ParameterBoolean
40+
from processing.core.parameters import ParameterString
41+
from processing.core.parameters import ParameterNumber
42+
from processing.core.parameters import getParameterFromString
43+
from processing.core.outputs import getOutputFromString
44+
45+
from TauDEMUtils import TauDEMUtils
46+
47+
48+
class TauDEMMultifileAlgorithm(GeoAlgorithm):
49+
50+
def __init__(self, descriptionfile):
51+
GeoAlgorithm.__init__(self)
52+
self.descriptionFile = descriptionfile
53+
self.defineCharacteristicsFromFile()
54+
55+
def getCopy(self):
56+
newone = TauDEMMultifileAlgorithm(self.descriptionFile)
57+
newone.provider = self.provider
58+
return newone
59+
60+
def getIcon(self):
61+
return QIcon(os.path.dirname(__file__) + '/../../images/taudem.png')
62+
63+
def defineCharacteristicsFromFile(self):
64+
lines = open(self.descriptionFile)
65+
line = lines.readline().strip('\n').strip()
66+
self.name = line
67+
line = lines.readline().strip('\n').strip()
68+
self.cmdName = line
69+
line = lines.readline().strip('\n').strip()
70+
self.group = line
71+
72+
line = lines.readline().strip('\n').strip()
73+
while line != '':
74+
try:
75+
line = line.strip('\n').strip()
76+
if line.startswith('Parameter'):
77+
param = getParameterFromString(line)
78+
self.addParameter(param)
79+
else:
80+
self.addOutput(getOutputFromString(line))
81+
line = lines.readline().strip('\n').strip()
82+
except Exception, e:
83+
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
84+
self.tr('Could not load TauDEM algorithm: %s\n%s' % (self.descriptionFile, line)))
85+
raise e
86+
lines.close()
87+
88+
def processAlgorithm(self, progress):
89+
commands = []
90+
commands.append(os.path.join(TauDEMUtils.mpiexecPath(), 'mpiexec'))
91+
92+
processNum = int(ProcessingConfig.getSetting(TauDEMUtils.MPI_PROCESSES))
93+
if processNum <= 0:
94+
raise GeoAlgorithmExecutionException(
95+
self.tr('Wrong number of MPI processes used. Please set '
96+
'correct number before running TauDEM algorithms.'))
97+
98+
commands.append('-n')
99+
commands.append(str(processNum))
100+
commands.append(os.path.join(TauDEMUtils.taudemMultifilePath(), self.cmdName))
101+
102+
for param in self.parameters:
103+
if param.value is None or param.value == '':
104+
continue
105+
if isinstance(param, ParameterNumber):
106+
commands.append(param.name)
107+
commands.append(str(param.value))
108+
if isinstance(param, (ParameterFile, ParameterVector)):
109+
commands.append(param.name)
110+
commands.append(param.value)
111+
elif isinstance(param, ParameterBoolean):
112+
if param.value and str(param.value).lower() == 'false':
113+
commands.append(param.name)
114+
elif isinstance(param, ParameterString):
115+
commands.append(param.name)
116+
commands.append(str(param.value))
117+
118+
for out in self.outputs:
119+
commands.append(out.name)
120+
commands.append(out.value)
121+
122+
TauDEMUtils.executeTauDEM(commands, progress)

python/plugins/processing/algs/taudem/TauDEMUtils.py

+24-4
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,22 @@
2626
__revision__ = '$Format:%H$'
2727

2828
import os
29-
from qgis.core import QgsApplication
3029
import subprocess
3130

31+
from PyQt4.QtCore import QCoreApplication
32+
from qgis.core import QgsApplication
33+
3234
from processing.core.ProcessingConfig import ProcessingConfig
3335
from processing.core.ProcessingLog import ProcessingLog
3436
from processing.tools.system import isMac
35-
from PyQt4.QtCore import QCoreApplication
3637

3738

3839
class TauDEMUtils:
3940

4041
TAUDEM_FOLDER = 'TAUDEM_FOLDER'
42+
TAUDEM_MULTIFILE_FOLDER = 'TAUDEM_MULTIFILE_FOLDER'
43+
TAUDEM_USE_SINGLEFILE = 'TAUDEM_USE_SINGLEFILE'
44+
TAUDEM_USE_MULTIFILE = 'TAUDEM_USE_MULTIFILE'
4145
MPIEXEC_FOLDER = 'MPIEXEC_FOLDER'
4246
MPI_PROCESSES = 'MPI_PROCESSES'
4347

@@ -57,6 +61,22 @@ def taudemPath():
5761
folder = testfolder
5862
return folder
5963

64+
@staticmethod
65+
def taudemMultifilePath():
66+
folder = ProcessingConfig.getSetting(TauDEMUtils.TAUDEM_MULTIFILE_FOLDER)
67+
if folder is None:
68+
folder = ''
69+
70+
if isMac():
71+
testfolder = os.path.join(QgsApplication.prefixPath(), 'bin')
72+
if os.path.exists(os.path.join(testfolder, 'slopearea')):
73+
folder = testfolder
74+
else:
75+
testfolder = '/usr/local/bin'
76+
if os.path.exists(os.path.join(testfolder, 'slopearea')):
77+
folder = testfolder
78+
return folder
79+
6080
@staticmethod
6181
def mpiexecPath():
6282
folder = ProcessingConfig.getSetting(TauDEMUtils.MPIEXEC_FOLDER)
@@ -75,8 +95,8 @@ def mpiexecPath():
7595

7696
@staticmethod
7797
def taudemDescriptionPath():
78-
return os.path.normpath(os.path.join(os.path.dirname(__file__),
79-
'description'))
98+
return os.path.normpath(
99+
os.path.join(os.path.dirname(__file__), 'description'))
80100

81101
@staticmethod
82102
def executeTauDEM(command, progress):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
D8 Contributing Area (multifile)
2+
aread8
3+
Basic Grid Analysis tools
4+
ParameterFile|-p|D8 Flow Direction Grid|True|False
5+
ParameterVector|-o|Outlets Shapefile|0|True
6+
ParameterFile|-wg|Weight Grid|True|True
7+
ParameterBoolean|-nc|Check for edge contamination|True
8+
OutputDirectory|-ad8|D8 Contributing Area Grid
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
D-Infinity Contributing Area (multifile)
2+
areadinf
3+
Basic Grid Analysis tools
4+
ParameterFile|-ang|D-Infinity Flow Direction Grid|True|False
5+
ParameterVector|-o|Outlets Shapefile|0|True
6+
ParameterFile|-wg|Weight Grid|True|True
7+
ParameterBoolean|-nc|Check for edge contamination|True
8+
OutputDirectory|-sca|D-Infinity Specific Catchment Area Grid
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
D8 Flow Directions (multifile)
2+
d8flowdir
3+
Basic Grid Analysis tools
4+
ParameterFile|-fel|Pit Filled Elevation Grid|True|False
5+
OutputDirectory|-p|D8 Flow Direction Grid
6+
OutputDirectory|-sd8|D8 Slope Grid

0 commit comments

Comments
 (0)