Skip to content
Permalink
Browse files
Merge pull request #4545 from rldhont/release-2_14-processing-rscript…
…s-outputs

[BUGFIX][Processing] R scripts do not have enough outputs
  • Loading branch information
rldhont committed May 16, 2017
2 parents 6feed19 + b830eab commit acd35753dcf2244aeb5f2bb1ebc3c0abbfe153cc
Showing with 80 additions and 3 deletions.
  1. +80 −3 python/plugins/processing/algs/r/RAlgorithm.py
@@ -51,7 +51,11 @@
from processing.core.outputs import OutputRaster
from processing.core.outputs import OutputHTML
from processing.core.outputs import OutputFile
from processing.core.outputs import OutputDirectory
from processing.core.outputs import OutputString
from processing.core.outputs import OutputNumber
from processing.tools.system import isWindows
from processing.tools.system import setTempOutput
from processing.script.WrongScriptException import WrongScriptException
from RUtils import RUtils

@@ -60,6 +64,7 @@ class RAlgorithm(GeoAlgorithm):

R_CONSOLE_OUTPUT = 'R_CONSOLE_OUTPUT'
RPLOTS = 'RPLOTS'
R_OUTPUT_VALUES = 'R_OUTPUT_VALUES'

def getCopy(self):
newone = RAlgorithm(self.descriptionFile)
@@ -97,6 +102,7 @@ def parseDescription(self, lines):
self.commands = []
self.showPlots = False
self.showConsoleOutput = False
self.saveOutputValues = False
self.useRasterPackage = True
self.passFileNames = False
self.verboseCommands = []
@@ -106,7 +112,7 @@ def parseDescription(self, lines):
if line.startswith('##'):
try:
self.processParameterLine(line)
except Exception:
except Exception as e:
raise WrongScriptException(
self.tr('Could not load R script: %s.\n Problem with line %s' % (self.descriptionFile, line)))
elif line.startswith('>'):
@@ -269,8 +275,24 @@ def processOutputParameterToken(self, token):
out = OutputVector()
elif token.lower().strip().startswith('table'):
out = OutputTable()
elif token.lower().strip().startswith('file'):
out = OutputFile()
else:
if token.lower().strip().startswith('file'):
out = OutputFile()
ext = token.strip()[len('file') + 1:]
if ext:
out.ext = ext
elif token.lower().strip().startswith('directory'):
out = OutputDirectory()
elif token.lower().strip().startswith('number'):
out = OutputNumber()
elif token.lower().strip().startswith('string'):
out = OutputString()

if not self.saveOutputValues and out:
outVal = OutputFile(RAlgorithm.R_OUTPUT_VALUES, self.tr('R Output values'), ext='txt')
outVal.hidden = True
self.addOutput(outVal)
self.saveOutputValues = True

return out

@@ -288,6 +310,10 @@ def processAlgorithm(self, progress):
progress.setCommand(line)
ProcessingLog.addToLog(ProcessingLog.LOG_INFO, loglines)
RUtils.executeRAlgorithm(self, progress)
if self.saveOutputValues:
with open(self.getOutputValue(RAlgorithm.R_OUTPUT_VALUES), 'r') as f:
lines = [line.strip() for line in f]
self.parseOutputValues(iter(lines))
if self.showPlots:
htmlfilename = self.getOutputValue(RAlgorithm.RPLOTS)
f = open(htmlfilename, 'w')
@@ -299,6 +325,37 @@ def processAlgorithm(self, progress):
f.write(RUtils.getConsoleOutput())
f.close()

def parseOutputValues(self, lines):
if not self.saveOutputValues:
return

out = None
ender = 0
line = lines.next().strip('\n').strip('\r')
while ender < 10:
if line.startswith('##'):
name = line.replace('#', '')
out = self.getOutputFromName(name)
else:
if line == '':
ender += 1
else:
ender = 0
if out:
if isinstance(out, OutputNumber):
out.setValue(float(line) if '.' in line else int(line))
elif isinstance(out, OutputString):
if not out.value:
out.setValue(line)
else:
out.value += '\n\r' + line
else:
out.setValue(line)
try:
line = lines.next().strip('\n').strip('\r')
except:
break

def getFullSetOfRCommands(self):
commands = []
commands += self.getImportCommands()
@@ -309,6 +366,15 @@ def getFullSetOfRCommands(self):

def getExportCommands(self):
commands = []

# Output Values
outputDataFile = None
if self.saveOutputValues:
outputDataFile = self.getOutputValue(RAlgorithm.R_OUTPUT_VALUES)
if not outputDataFile:
setTempOutput(self.getOutputFromName(RAlgorithm.R_OUTPUT_VALUES), self)
outputDataFile = self.getOutputValue(RAlgorithm.R_OUTPUT_VALUES)

for out in self.outputs:
if isinstance(out, OutputRaster):
value = out.value
@@ -334,6 +400,9 @@ def getExportCommands(self):
value = out.value
value = value.replace('\\', '/')
commands.append('write.csv(' + out.name + ',"' + value + '")')
elif out.name != RAlgorithm.R_OUTPUT_VALUES:
commands.append('cat("##' + out.name + '",file="' + outputDataFile + '",sep="\n",append=TRUE)')
commands.append('cat(' + out.name + ',file="' + outputDataFile + '",sep="\n",append=TRUE)')

if self.showPlots:
commands.append('dev.off()')
@@ -358,6 +427,7 @@ def getImportCommands(self):
commands.append('library("raster")')
commands.append('library("rgdal")')

# Add parameters
for param in self.parameters:
if isinstance(param, ParameterRaster):
if param.value is None:
@@ -476,6 +546,13 @@ def getImportCommands(self):
s += ')\n'
commands.append(s)

# Set outputs
for out in self.outputs:
if isinstance(out, OutputFile) or isinstance(out, OutputDirectory):
if not out.value:
setTempOutput(out, self)
commands.append(out.name + ' = "' + out.value + '"')

if self.showPlots:
htmlfilename = self.getOutputValue(RAlgorithm.RPLOTS)
self.plotsFilename = htmlfilename + '.png'

0 comments on commit acd3575

Please sign in to comment.