1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package ubic.basecode.util.r;
20
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import org.rosuda.REngine.REXP;
25 import org.rosuda.REngine.REXPMismatchException;
26 import org.rosuda.REngine.REngine;
27 import org.rosuda.REngine.REngineException;
28 import org.rosuda.REngine.RList;
29 import org.rosuda.REngine.JRI.JRIEngine;
30
31 import ubic.basecode.dataStructure.matrix.DoubleMatrix;
32 import ubic.basecode.dataStructure.matrix.DoubleMatrixFactory;
33
34
35
36
37
38
39
40
41
42 public class JRIClient extends AbstractRClient {
43
44 private static REngine connection = null;
45
46 static {
47 try {
48 System.loadLibrary( "jri" );
49
50
51
52
53 connection = new JRIEngine();
54 } catch ( REngineException e ) {
55 throw new RuntimeException( "JRI could not be initilized" );
56 } catch ( UnsatisfiedLinkError e ) {
57
58 log.warn( e + " " + System.getProperty( "java.library.path" ) );
59 }
60 }
61
62 public static boolean ready() {
63 return connection != null;
64 }
65
66
67
68
69
70
71 @Override
72 public void assign( String argName, double[] arg ) {
73 try {
74 connection.assign( argName, arg );
75 } catch ( REngineException e ) {
76 throw new RuntimeException( e );
77 }
78 }
79
80
81
82
83
84
85 @Override
86 public void assign( String arg0, int[] arg1 ) {
87 try {
88 connection.assign( arg0, arg1 );
89 } catch ( REngineException e ) {
90 throw new RuntimeException( e );
91 }
92 }
93
94
95
96
97
98
99 @Override
100 public void assign( String sym, String ct ) {
101 try {
102 connection.assign( sym, ct );
103 } catch ( REngineException e ) {
104 throw new RuntimeException( e );
105 }
106 }
107
108
109
110
111
112
113 @Override
114 public void assign( String argName, String[] array ) {
115 try {
116 connection.assign( argName, array );
117 } catch ( REngineException e ) {
118 throw new RuntimeException( e );
119 }
120 }
121
122 @Override
123 public void disconnect() {
124
125 }
126
127 @Override
128 public REXP eval( String command ) {
129 REXP result;
130 int key = connection.lock();
131 try {
132
133 result = connection.parseAndEval( "try(" + command + ", silent=T)" );
134
135 if ( result == null ) {
136 throw new RuntimeException( "Error from R, could not sucessfully evaluate: " + command );
137 }
138
139 if ( !result.isString() ) {
140 return result;
141 }
142 String a = result.asString();
143
144
145
146
147 if ( a != null && a.startsWith( "Error" ) ) {
148 throw new RuntimeException( "Error from R when running " + command + ": " + a );
149 }
150
151 return result;
152 } catch ( REngineException e ) {
153 throw new RuntimeException( e );
154 } catch ( REXPMismatchException e ) {
155 throw new RuntimeException( e );
156 } finally {
157 connection.unlock( key );
158 }
159 }
160
161
162
163
164
165
166 @Override
167 public String getLastError() {
168 return "Sorry, no information";
169 }
170
171 @Override
172 public boolean isConnected() {
173 return true;
174 }
175
176
177
178
179
180
181 @Override
182 public DoubleMatrix<String, String> retrieveMatrix( String variableName ) {
183 log.debug( "Retrieving " + variableName );
184 REXP r = this.eval( variableName );
185 if ( r == null ) throw new IllegalArgumentException( variableName + " not found in R context" );
186
187 double[][] results;
188 try {
189 results = r.asDoubleMatrix();
190 } catch ( REXPMismatchException e ) {
191 throw new RuntimeException( e );
192 }
193
194 if ( results == null ) throw new RuntimeException( "Failed to get back matrix for variable " + variableName );
195
196 DoubleMatrix<String, String> resultObject = DoubleMatrixFactory.dense( results );
197
198 retrieveRowAndColumnNames( variableName, resultObject );
199 return resultObject;
200
201 }
202
203
204
205
206
207
208 @Override
209 public void voidEval( String command ) {
210 eval( command );
211 }
212
213
214
215
216
217
218
219
220 private void retrieveRowAndColumnNames( String variableName, DoubleMatrix<String, String> resultObject ) {
221 log.debug( "Getting row & column names names" );
222
223 REXP r1 = this.eval( "dimnames(" + variableName + ")" );
224 RList asList;
225 try {
226 asList = r1.asList();
227 } catch ( REXPMismatchException e1 ) {
228 log.warn( "Matrix had no valid dimnames" );
229 return;
230 }
231
232 if ( asList == null ) {
233 return;
234 }
235
236 REXP rowNamesREXP = asList.at( 0 );
237 REXP colNamesREXP = asList.at( 1 );
238
239 if ( rowNamesREXP != null ) {
240 log.debug( "Got row names" );
241 String[] rowNamesAr;
242 try {
243 rowNamesAr = rowNamesREXP.asStrings();
244 } catch ( REXPMismatchException e ) {
245 log.warn( "Invalid rownames" );
246 return;
247 }
248 List<String> rowNames = new ArrayList<String>();
249 for ( String rowName : rowNamesAr ) {
250 rowNames.add( rowName );
251 }
252 resultObject.setRowNames( rowNames );
253 } else {
254 log.debug( "No row names" );
255 }
256
257
258 if ( colNamesREXP != null ) {
259 String[] colNamesAr;
260 try {
261 colNamesAr = colNamesREXP.asStrings();
262 } catch ( REXPMismatchException e ) {
263 return;
264 }
265 log.debug( "Got column names" );
266 List<String> colNames = new ArrayList<String>();
267 for ( String colName : colNamesAr ) {
268 colNames.add( colName );
269 }
270 resultObject.setColumnNames( colNames );
271 } else {
272 log.debug( "No column names" );
273 }
274 if ( log.isDebugEnabled() ) log.debug( resultObject.toString() );
275 }
276
277 }