1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkRInterface.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 /*-------------------------------------------------------------------------
16 Copyright 2009 Sandia Corporation.
17 Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
18 the U.S. Government retains certain rights in this software.
19 -------------------------------------------------------------------------*/
20
21 #include "vtkRInterface.h"
22
23 #undef HAVE_UINTPTR_T
24 #ifdef HAVE_VTK_UINTPTR_T
25 #define HAVE_UINTPTR_T HAVE_VTK_UINTPTR_T
26 #ifndef WIN32
27 #include <stdint.h>
28 #endif
29 #endif
30
31 #include "vtkInformation.h"
32 #include "vtkInformationVector.h"
33 #include "vtkObjectFactory.h"
34 #include "vtkDataArray.h"
35 #include "vtkRAdapter.h"
36
37 vtkStandardNewMacro(vtkRInterface);
38
39 #include "R.h"
40 #include "Rmath.h"
41 #include "Rembedded.h"
42 #include "Rversion.h"
43 #include "Rdefines.h"
44
45 #ifndef WIN32
46 #define CSTACK_DEFNS
47 #define R_INTERFACE_PTRS
48 #include "Rinterface.h"
49 #endif
50
51 #include "R_ext/Parse.h"
52
53 #include "vtksys/SystemTools.hxx"
54
55 /**
56 * This global boolean is used to keep track of whether or not R has been
57 * initialized. Rf_initialize_R() cannot be called more than once, yet
58 * R provides no way to detect whether or not it has already been called.
59 * In previous versions of this code we used atexit() to shut down the R
60 * interface, but this causes nondeterministic errors when working with R's
61 * parallel library.
62 **/
63 bool VTK_R_INITIALIZED = false;
64
65 class vtkImplementationRSingleton
66 {
67 public:
68 static vtkImplementationRSingleton* Instance();
69
InitializeR()70 void InitializeR()
71 {
72
73 if(this->Rinitialized)
74 {
75 this->refcount++;
76 return;
77 }
78
79 #ifndef WIN32
80 R_SignalHandlers = 0;
81 #endif
82
83 const char* path = vtksys::SystemTools::GetEnv("R_HOME");
84 if (!path)
85 {
86 std::string newPath = "R_HOME=";
87 newPath=newPath+VTK_R_HOME;
88 vtksys::SystemTools::PutEnv(newPath.c_str());
89 }
90 const char *R_argv[]= {"vtkRInterface", "--gui=none", "--no-save", "--no-readline", "--silent"};
91
92 if (!VTK_R_INITIALIZED)
93 {
94 Rf_initialize_R(sizeof(R_argv)/sizeof(R_argv[0]),
95 const_cast<char **>(R_argv));
96
97 #ifdef CSTACK_DEFNS
98 R_CStackLimit = (uintptr_t)-1;
99 #endif
100
101 #ifndef WIN32
102 R_Interactive = static_cast<Rboolean>(TRUE);
103 #endif
104 setup_Rmainloop();
105
106 VTK_R_INITIALIZED = true;
107 }
108
109 this->Rinitialized = 1;
110 this->refcount++;
111
112 std::string rcommand;
113 rcommand.append("f<-file(paste(tempdir(), \"/Routput.txt\", sep = \"\"), open=\"wt+\")\nsink(f)\n");
114 this->tmpFilePath.clear();
115 this->tmpFilePath.append(R_TempDir);
116 #ifdef WIN32
117 this->tmpFilePath.append("\\Routput.txt");
118 #else
119 this->tmpFilePath.append("/Routput.txt");
120 #endif
121
122 ParseStatus status;
123 SEXP cmdSexp, cmdexpr = R_NilValue;
124 int error;
125
126
127 PROTECT(cmdSexp = allocVector(STRSXP, 1));
128 SET_STRING_ELT(cmdSexp, 0, mkChar(rcommand.c_str()));
129
130 cmdexpr = PROTECT(R_ParseVector(cmdSexp, -1, &status, R_NilValue));
131 for(int i = 0; i < length(cmdexpr); i++)
132 {
133 R_tryEval(VECTOR_ELT(cmdexpr, i),NULL,&error);
134 }
135 UNPROTECT(2);
136
137 };
138
GetROutputFilePath()139 const char* GetROutputFilePath()
140 {
141 return tmpFilePath.c_str();
142 };
143
CloseR()144 void CloseR()
145 {
146 this->refcount--;
147 if (this->refcount < 1 && ins)
148 {
149 delete ins;
150 ins = NULL;
151 }
152 };
153
154 protected:
155
156 ~vtkImplementationRSingleton();
157
158 vtkImplementationRSingleton();
159
160 vtkImplementationRSingleton(const vtkImplementationRSingleton&);
161
162 vtkImplementationRSingleton& operator=(const vtkImplementationRSingleton&);
163
164 private:
165
166 std::string tmpFilePath;
167 int refcount;
168 int Rinitialized;
169 static vtkImplementationRSingleton* ins;
170 static void shutdownR(void);
171
172 };
173
174
Instance()175 vtkImplementationRSingleton* vtkImplementationRSingleton::Instance()
176 {
177
178 if(ins == 0)
179 {
180 ins = new vtkImplementationRSingleton;
181 }
182
183 ins->InitializeR();
184 return(ins);
185
186 }
187
188
~vtkImplementationRSingleton()189 vtkImplementationRSingleton::~vtkImplementationRSingleton()
190 {
191
192 R_CleanTempDir();
193 Rf_endEmbeddedR(0);
194
195 }
196
vtkImplementationRSingleton()197 vtkImplementationRSingleton::vtkImplementationRSingleton()
198 {
199
200 this->refcount = 0;
201 this->Rinitialized = 0;
202
203 }
204
205 vtkImplementationRSingleton* vtkImplementationRSingleton::ins = 0;
206
207 //----------------------------------------------------------------------------
vtkRInterface()208 vtkRInterface::vtkRInterface()
209 {
210
211 this->rs = vtkImplementationRSingleton::Instance();
212 this->buffer = 0;
213 this->buffer_size = 0;
214 this->vra = vtkRAdapter::New();
215
216 }
217
218 //----------------------------------------------------------------------------
~vtkRInterface()219 vtkRInterface::~vtkRInterface()
220 {
221
222 this->rs->CloseR();
223 this->vra->Delete();
224
225 }
226
EvalRscript(const char * string,bool showRoutput)227 int vtkRInterface::EvalRscript(const char *string, bool showRoutput)
228 {
229
230 ParseStatus status;
231 SEXP cmdSexp, cmdexpr = R_NilValue;
232 SEXP ans;
233 int i;
234 int error;
235
236 PROTECT(cmdSexp = allocVector(STRSXP, 1));
237 SET_STRING_ELT(cmdSexp, 0, mkChar(string));
238
239 cmdexpr = PROTECT(R_ParseVector(cmdSexp, -1, &status, R_NilValue));
240 switch (status)
241 {
242 case PARSE_OK:
243 for(i = 0; i < length(cmdexpr); i++)
244 {
245 ans = R_tryEval(VECTOR_ELT(cmdexpr, i),NULL,&error);
246 if (error)
247 {
248 return 1;
249 }
250 if(showRoutput)
251 {
252 PrintValue(ans);
253 }
254 }
255 break;
256
257 case PARSE_INCOMPLETE:
258 vtkErrorMacro(<<"R parse status is PARSE_INCOMPLETE");
259 /* need to read another line */
260 break;
261
262 case PARSE_NULL:
263 vtkErrorMacro(<<"R parse status is PARSE_NULL");
264 return 1;
265
266 case PARSE_ERROR:
267 vtkErrorMacro(<<"R parse status is PARSE_ERROR");
268 return 1;
269
270 case PARSE_EOF:
271 vtkErrorMacro(<<"R parse status is PARSE_EOF");
272 break;
273
274 default:
275 vtkErrorMacro(<<"R parse status is NOT DOCUMENTED");
276 return 1;
277 }
278 UNPROTECT(2);
279 this->FillOutputBuffer();
280 return 0;
281
282 }
283
EvalRcommand(const char * funcName,int param)284 int vtkRInterface::EvalRcommand(const char *funcName, int param)
285 {
286
287 SEXP e;
288 SEXP arg;
289 int errorOccurred;
290
291 PROTECT(arg = allocVector(INTSXP, 1));
292 INTEGER(arg)[0] = param;
293 PROTECT(e = lang2(install(funcName), arg));
294
295 R_tryEval(e, R_GlobalEnv, &errorOccurred);
296
297 UNPROTECT(2);
298 return(errorOccurred);
299
300 }
301
AssignVTKDataArrayToRVariable(vtkDataArray * da,const char * RVariableName)302 void vtkRInterface::AssignVTKDataArrayToRVariable(vtkDataArray* da, const char* RVariableName)
303 {
304
305 SEXP s;
306 s = this->vra->VTKDataArrayToR(da);
307 defineVar(install(RVariableName), s, R_GlobalEnv);
308
309 }
310
AssignVTKArrayToRVariable(vtkArray * da,const char * RVariableName)311 void vtkRInterface::AssignVTKArrayToRVariable(vtkArray* da, const char* RVariableName)
312 {
313
314 SEXP s;
315 s = this->vra->VTKArrayToR(da);
316 defineVar(install(RVariableName), s, R_GlobalEnv);
317
318 }
319
AssignVTKTreeToRVariable(vtkTree * tr,const char * RVariableName)320 void vtkRInterface::AssignVTKTreeToRVariable(vtkTree* tr, const char* RVariableName)
321 {
322
323 SEXP s;
324 s = this->vra->VTKTreeToR(tr);
325 defineVar(install(RVariableName), s, R_GlobalEnv);
326
327 }
328
329
AssignRVariableToVTKTree(const char * RVariableName)330 vtkTree* vtkRInterface::AssignRVariableToVTKTree(const char* RVariableName)
331 {
332
333 SEXP s;
334
335 s = findVar(install(RVariableName), R_GlobalEnv);
336
337 if(s != R_UnboundValue)
338 return(this->vra->RToVTKTree(s));
339 else
340 return(0);
341
342 }
343
AssignRVariableToVTKDataArray(const char * RVariableName)344 vtkDataArray* vtkRInterface::AssignRVariableToVTKDataArray(const char* RVariableName)
345 {
346
347 SEXP s;
348
349 s = findVar(install(RVariableName), R_GlobalEnv);
350
351 if(s != R_UnboundValue)
352 return(this->vra->RToVTKDataArray(s));
353 else
354 return(0);
355
356 }
357
AssignRVariableToVTKArray(const char * RVariableName)358 vtkArray* vtkRInterface::AssignRVariableToVTKArray(const char* RVariableName)
359 {
360
361 SEXP s;
362
363 s = findVar(install(RVariableName), R_GlobalEnv);
364
365 if(s != R_UnboundValue)
366 return(this->vra->RToVTKArray(s));
367 else
368 return(0);
369
370 }
371
AssignRVariableToVTKTable(const char * RVariableName)372 vtkTable* vtkRInterface::AssignRVariableToVTKTable(const char* RVariableName)
373 {
374
375 SEXP s;
376
377 s = findVar(install(RVariableName), R_GlobalEnv);
378
379 if(s != R_UnboundValue)
380 return(this->vra->RToVTKTable(s));
381 else
382 return(0);
383
384 }
385
AssignVTKTableToRVariable(vtkTable * table,const char * RVariableName)386 void vtkRInterface::AssignVTKTableToRVariable(vtkTable* table, const char* RVariableName)
387 {
388
389 SEXP s;
390 s = this->vra->VTKTableToR(table);
391 defineVar(install(RVariableName), s, R_GlobalEnv);
392
393 }
394
OutputBuffer(char * p,int n)395 int vtkRInterface::OutputBuffer(char* p, int n)
396 {
397
398 this->buffer = p;
399 this->buffer_size = n;
400 if(this->buffer && (this->buffer_size > 0) )
401 {
402 this->buffer[0] = '\0';
403 }
404 return(1);
405
406 }
407
FillOutputBuffer()408 int vtkRInterface::FillOutputBuffer()
409 {
410
411 FILE *fp;
412 long len;
413 long rlen;
414 long tlen;
415
416 if(this->buffer && (this->buffer_size > 0) )
417 {
418 fp = fopen(this->rs->GetROutputFilePath(),"rb");
419
420 if(!fp)
421 {
422 vtkErrorMacro(<<"Can't open input file named " << this->rs->GetROutputFilePath());
423 return(0);
424 }
425
426 fseek(fp,0,SEEK_END);
427 len = ftell(fp);
428
429 if(len == 0)
430 {
431 fclose(fp);
432 return(1);
433 }
434
435 tlen = ((len >= this->buffer_size) ? this->buffer_size-1 : len);
436 fseek(fp,len-tlen,SEEK_SET);
437 rlen = static_cast<long>(fread(this->buffer,1,tlen,fp));
438 this->buffer[tlen] = '\0';
439
440 fclose(fp);
441
442 if (rlen != tlen)
443 {
444 vtkErrorMacro(<<"Error while reading file " << this->rs->GetROutputFilePath());
445 return(0);
446 }
447
448 return(1);
449
450 }
451 else
452 {
453 return(0);
454 }
455
456 }
457
PrintSelf(ostream & os,vtkIndent indent)458 void vtkRInterface::PrintSelf(ostream& os, vtkIndent indent)
459 {
460
461 this->Superclass::PrintSelf(os, indent);
462
463 os << indent << "buffer_size: " << this->buffer_size << endl;
464 os << indent << "buffer: " << (this->buffer ? this->buffer : "NULL") << endl;
465
466 if(this->vra)
467 {
468 this->vra->PrintSelf(os, indent);
469 }
470
471 }
472
473