53
53
from processing .core .outputs import OutputRaster
54
54
from processing .core .outputs import OutputHTML
55
55
from processing .core .outputs import OutputFile
56
+ from processing .core .outputs import OutputDirectory
57
+ from processing .core .outputs import OutputString
58
+ from processing .core .outputs import OutputNumber
56
59
from processing .tools .system import isWindows
60
+ from processing .tools .system import setTempOutput
57
61
from processing .script .WrongScriptException import WrongScriptException
58
62
from .RUtils import RUtils
59
63
@@ -62,6 +66,7 @@ class RAlgorithm(GeoAlgorithm):
62
66
63
67
R_CONSOLE_OUTPUT = 'R_CONSOLE_OUTPUT'
64
68
RPLOTS = 'RPLOTS'
69
+ R_OUTPUT_VALUES = 'R_OUTPUT_VALUES'
65
70
66
71
def getCopy (self ):
67
72
newone = RAlgorithm (self .descriptionFile )
@@ -99,6 +104,7 @@ def parseDescription(self, lines):
99
104
self .commands = []
100
105
self .showPlots = False
101
106
self .showConsoleOutput = False
107
+ self .saveOutputValues = False
102
108
self .useRasterPackage = True
103
109
self .passFileNames = False
104
110
self .verboseCommands = []
@@ -108,7 +114,7 @@ def parseDescription(self, lines):
108
114
if line .startswith ('##' ):
109
115
try :
110
116
self .processParameterLine (line )
111
- except Exception :
117
+ except Exception as e :
112
118
raise WrongScriptException (
113
119
self .tr ('Could not load R script: %s.\n Problem with line %s' % (self .descriptionFile , line )))
114
120
elif line .startswith ('>' ):
@@ -282,8 +288,24 @@ def processOutputParameterToken(self, token):
282
288
out = OutputVector ()
283
289
elif token .lower ().strip ().startswith ('table' ):
284
290
out = OutputTable ()
285
- elif token .lower ().strip ().startswith ('file' ):
286
- out = OutputFile ()
291
+ else :
292
+ if token .lower ().strip ().startswith ('file' ):
293
+ out = OutputFile ()
294
+ ext = token .strip ()[len ('file' ) + 1 :]
295
+ if ext :
296
+ out .ext = ext
297
+ elif token .lower ().strip ().startswith ('directory' ):
298
+ out = OutputDirectory ()
299
+ elif token .lower ().strip ().startswith ('number' ):
300
+ out = OutputNumber ()
301
+ elif token .lower ().strip ().startswith ('string' ):
302
+ out = OutputString ()
303
+
304
+ if not self .saveOutputValues and out :
305
+ outVal = OutputFile (RAlgorithm .R_OUTPUT_VALUES , self .tr ('R Output values' ), ext = 'txt' )
306
+ outVal .hidden = True
307
+ self .addOutput (outVal )
308
+ self .saveOutputValues = True
287
309
288
310
return out
289
311
@@ -301,6 +323,10 @@ def processAlgorithm(self, progress):
301
323
progress .setCommand (line )
302
324
ProcessingLog .addToLog (ProcessingLog .LOG_INFO , loglines )
303
325
RUtils .executeRAlgorithm (self , progress )
326
+ if self .saveOutputValues :
327
+ with open (self .getOutputValue (RAlgorithm .R_OUTPUT_VALUES ), 'r' ) as f :
328
+ lines = [line .strip () for line in f ]
329
+ self .parseOutputValues (iter (lines ))
304
330
if self .showPlots :
305
331
htmlfilename = self .getOutputValue (RAlgorithm .RPLOTS )
306
332
f = open (htmlfilename , 'w' )
@@ -312,6 +338,37 @@ def processAlgorithm(self, progress):
312
338
f .write (RUtils .getConsoleOutput ())
313
339
f .close ()
314
340
341
+ def parseOutputValues (self , lines ):
342
+ if not self .saveOutputValues :
343
+ return
344
+
345
+ out = None
346
+ ender = 0
347
+ line = lines .next ().strip ('\n ' ).strip ('\r ' )
348
+ while ender < 10 :
349
+ if line .startswith ('##' ):
350
+ name = line .replace ('#' , '' )
351
+ out = self .getOutputFromName (name )
352
+ else :
353
+ if line == '' :
354
+ ender += 1
355
+ else :
356
+ ender = 0
357
+ if out :
358
+ if isinstance (out , OutputNumber ):
359
+ out .setValue (float (line ) if '.' in line else int (line ))
360
+ elif isinstance (out , OutputString ):
361
+ if not out .value :
362
+ out .setValue (line )
363
+ else :
364
+ out .value += '\n \r ' + line
365
+ else :
366
+ out .setValue (line )
367
+ try :
368
+ line = lines .next ().strip ('\n ' ).strip ('\r ' )
369
+ except :
370
+ break
371
+
315
372
def getFullSetOfRCommands (self ):
316
373
commands = []
317
374
commands += self .getImportCommands ()
@@ -322,6 +379,15 @@ def getFullSetOfRCommands(self):
322
379
323
380
def getExportCommands (self ):
324
381
commands = []
382
+
383
+ # Output Values
384
+ outputDataFile = None
385
+ if self .saveOutputValues :
386
+ outputDataFile = self .getOutputValue (RAlgorithm .R_OUTPUT_VALUES )
387
+ if not outputDataFile :
388
+ setTempOutput (self .getOutputFromName (RAlgorithm .R_OUTPUT_VALUES ), self )
389
+ outputDataFile = self .getOutputValue (RAlgorithm .R_OUTPUT_VALUES )
390
+
325
391
for out in self .outputs :
326
392
if isinstance (out , OutputRaster ):
327
393
value = out .value
@@ -347,6 +413,9 @@ def getExportCommands(self):
347
413
value = out .value
348
414
value = value .replace ('\\ ' , '/' )
349
415
commands .append ('write.csv(' + out .name + ',"' + value + '")' )
416
+ elif out .name != RAlgorithm .R_OUTPUT_VALUES :
417
+ commands .append ('cat("##' + out .name + '",file="' + outputDataFile + '",sep="\n ",append=TRUE)' )
418
+ commands .append ('cat(' + out .name + ',file="' + outputDataFile + '",sep="\n ",append=TRUE)' )
350
419
351
420
if self .showPlots :
352
421
commands .append ('dev.off()' )
@@ -371,6 +440,7 @@ def getImportCommands(self):
371
440
commands .append ('library("raster")' )
372
441
commands .append ('library("rgdal")' )
373
442
443
+ # Add parameters
374
444
for param in self .parameters :
375
445
if isinstance (param , ParameterRaster ):
376
446
if param .value is None :
@@ -489,6 +559,13 @@ def getImportCommands(self):
489
559
s += ')\n '
490
560
commands .append (s )
491
561
562
+ # Set outputs
563
+ for out in self .outputs :
564
+ if isinstance (out , OutputFile ) or isinstance (out , OutputDirectory ):
565
+ if not out .value :
566
+ setTempOutput (out , self )
567
+ commands .append (out .name + ' = "' + out .value + '"' )
568
+
492
569
if self .showPlots :
493
570
htmlfilename = self .getOutputValue (RAlgorithm .RPLOTS )
494
571
self .plotsFilename = htmlfilename + '.png'
0 commit comments