51
51
from processing .core .outputs import OutputRaster
52
52
from processing .core .outputs import OutputHTML
53
53
from processing .core .outputs import OutputFile
54
+ from processing .core .outputs import OutputDirectory
55
+ from processing .core .outputs import OutputString
56
+ from processing .core .outputs import OutputNumber
54
57
from processing .tools .system import isWindows
58
+ from processing .tools .system import setTempOutput
55
59
from processing .script .WrongScriptException import WrongScriptException
56
60
from RUtils import RUtils
57
61
@@ -60,6 +64,7 @@ class RAlgorithm(GeoAlgorithm):
60
64
61
65
R_CONSOLE_OUTPUT = 'R_CONSOLE_OUTPUT'
62
66
RPLOTS = 'RPLOTS'
67
+ R_OUTPUT_VALUES = 'R_OUTPUT_VALUES'
63
68
64
69
def getCopy (self ):
65
70
newone = RAlgorithm (self .descriptionFile )
@@ -97,6 +102,7 @@ def parseDescription(self, lines):
97
102
self .commands = []
98
103
self .showPlots = False
99
104
self .showConsoleOutput = False
105
+ self .saveOutputValues = False
100
106
self .useRasterPackage = True
101
107
self .passFileNames = False
102
108
self .verboseCommands = []
@@ -106,7 +112,7 @@ def parseDescription(self, lines):
106
112
if line .startswith ('##' ):
107
113
try :
108
114
self .processParameterLine (line )
109
- except Exception :
115
+ except Exception as e :
110
116
raise WrongScriptException (
111
117
self .tr ('Could not load R script: %s.\n Problem with line %s' % (self .descriptionFile , line )))
112
118
elif line .startswith ('>' ):
@@ -269,8 +275,24 @@ def processOutputParameterToken(self, token):
269
275
out = OutputVector ()
270
276
elif token .lower ().strip ().startswith ('table' ):
271
277
out = OutputTable ()
272
- elif token .lower ().strip ().startswith ('file' ):
273
- out = OutputFile ()
278
+ else :
279
+ if token .lower ().strip ().startswith ('file' ):
280
+ out = OutputFile ()
281
+ ext = token .strip ()[len ('file' ) + 1 :]
282
+ if ext :
283
+ out .ext = ext
284
+ elif token .lower ().strip ().startswith ('directory' ):
285
+ out = OutputDirectory ()
286
+ elif token .lower ().strip ().startswith ('number' ):
287
+ out = OutputNumber ()
288
+ elif token .lower ().strip ().startswith ('string' ):
289
+ out = OutputString ()
290
+
291
+ if not self .saveOutputValues and out :
292
+ outVal = OutputFile (RAlgorithm .R_OUTPUT_VALUES , self .tr ('R Output values' ), ext = 'txt' )
293
+ outVal .hidden = True
294
+ self .addOutput (outVal )
295
+ self .saveOutputValues = True
274
296
275
297
return out
276
298
@@ -288,6 +310,10 @@ def processAlgorithm(self, progress):
288
310
progress .setCommand (line )
289
311
ProcessingLog .addToLog (ProcessingLog .LOG_INFO , loglines )
290
312
RUtils .executeRAlgorithm (self , progress )
313
+ if self .saveOutputValues :
314
+ with open (self .getOutputValue (RAlgorithm .R_OUTPUT_VALUES ), 'r' ) as f :
315
+ lines = [line .strip () for line in f ]
316
+ self .parseOutputValues (iter (lines ))
291
317
if self .showPlots :
292
318
htmlfilename = self .getOutputValue (RAlgorithm .RPLOTS )
293
319
f = open (htmlfilename , 'w' )
@@ -299,6 +325,37 @@ def processAlgorithm(self, progress):
299
325
f .write (RUtils .getConsoleOutput ())
300
326
f .close ()
301
327
328
+ def parseOutputValues (self , lines ):
329
+ if not self .saveOutputValues :
330
+ return
331
+
332
+ out = None
333
+ ender = 0
334
+ line = lines .next ().strip ('\n ' ).strip ('\r ' )
335
+ while ender < 10 :
336
+ if line .startswith ('##' ):
337
+ name = line .replace ('#' , '' )
338
+ out = self .getOutputFromName (name )
339
+ else :
340
+ if line == '' :
341
+ ender += 1
342
+ else :
343
+ ender = 0
344
+ if out :
345
+ if isinstance (out , OutputNumber ):
346
+ out .setValue (float (line ) if '.' in line else int (line ))
347
+ elif isinstance (out , OutputString ):
348
+ if not out .value :
349
+ out .setValue (line )
350
+ else :
351
+ out .value += '\n \r ' + line
352
+ else :
353
+ out .setValue (line )
354
+ try :
355
+ line = lines .next ().strip ('\n ' ).strip ('\r ' )
356
+ except :
357
+ break
358
+
302
359
def getFullSetOfRCommands (self ):
303
360
commands = []
304
361
commands += self .getImportCommands ()
@@ -309,6 +366,15 @@ def getFullSetOfRCommands(self):
309
366
310
367
def getExportCommands (self ):
311
368
commands = []
369
+
370
+ # Output Values
371
+ outputDataFile = None
372
+ if self .saveOutputValues :
373
+ outputDataFile = self .getOutputValue (RAlgorithm .R_OUTPUT_VALUES )
374
+ if not outputDataFile :
375
+ setTempOutput (self .getOutputFromName (RAlgorithm .R_OUTPUT_VALUES ), self )
376
+ outputDataFile = self .getOutputValue (RAlgorithm .R_OUTPUT_VALUES )
377
+
312
378
for out in self .outputs :
313
379
if isinstance (out , OutputRaster ):
314
380
value = out .value
@@ -334,6 +400,9 @@ def getExportCommands(self):
334
400
value = out .value
335
401
value = value .replace ('\\ ' , '/' )
336
402
commands .append ('write.csv(' + out .name + ',"' + value + '")' )
403
+ elif out .name != RAlgorithm .R_OUTPUT_VALUES :
404
+ commands .append ('cat("##' + out .name + '",file="' + outputDataFile + '",sep="\n ",append=TRUE)' )
405
+ commands .append ('cat(' + out .name + ',file="' + outputDataFile + '",sep="\n ",append=TRUE)' )
337
406
338
407
if self .showPlots :
339
408
commands .append ('dev.off()' )
@@ -358,6 +427,7 @@ def getImportCommands(self):
358
427
commands .append ('library("raster")' )
359
428
commands .append ('library("rgdal")' )
360
429
430
+ # Add parameters
361
431
for param in self .parameters :
362
432
if isinstance (param , ParameterRaster ):
363
433
if param .value is None :
@@ -476,6 +546,13 @@ def getImportCommands(self):
476
546
s += ')\n '
477
547
commands .append (s )
478
548
549
+ # Set outputs
550
+ for out in self .outputs :
551
+ if isinstance (out , OutputFile ) or isinstance (out , OutputDirectory ):
552
+ if not out .value :
553
+ setTempOutput (out , self )
554
+ commands .append (out .name + ' = "' + out .value + '"' )
555
+
479
556
if self .showPlots :
480
557
htmlfilename = self .getOutputValue (RAlgorithm .RPLOTS )
481
558
self .plotsFilename = htmlfilename + '.png'
0 commit comments