001 /* 002 * Copyright (C) 2008-2010 by Holger Arndt 003 * 004 * This file is part of the Universal Java Matrix Package (UJMP). 005 * See the NOTICE file distributed with this work for additional 006 * information regarding copyright ownership and licensing. 007 * 008 * UJMP is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation; either version 2 011 * of the License, or (at your option) any later version. 012 * 013 * UJMP is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU Lesser General Public License for more details. 017 * 018 * You should have received a copy of the GNU Lesser General Public 019 * License along with UJMP; if not, write to the 020 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 021 * Boston, MA 02110-1301 USA 022 */ 023 024 package org.ujmp.core.util; 025 026 import java.io.BufferedReader; 027 import java.io.BufferedWriter; 028 import java.io.File; 029 import java.io.IOException; 030 import java.io.InputStreamReader; 031 import java.io.OutputStreamWriter; 032 033 import org.ujmp.core.Matrix; 034 import org.ujmp.core.enums.FileFormat; 035 036 public class R { 037 038 public static String[] SEARCH = new String[] {}; 039 040 static { 041 try { 042 SEARCH = new String[] { System.getProperty("R"), "/usr/bin/R", "/opt/R/bin/R" }; 043 } catch (Exception e) { 044 } 045 } 046 047 public static final int POLLINTERVAL = 100; 048 049 public static final int MAXPOLLS = 10; 050 051 private BufferedReader input = null; 052 053 private BufferedWriter output = null; 054 055 private BufferedReader error = null; 056 057 private Process rProcess = null; 058 059 private boolean running = false; 060 061 private static R r = null; 062 063 private static String pathToR = null; 064 065 public static synchronized R getInstance() throws Exception { 066 if (r == null) { 067 r = getInstance(findR()); 068 } 069 return r; 070 } 071 072 public static synchronized R getInstance(String pathToR) throws Exception { 073 if (r == null) { 074 r = new R(pathToR); 075 } 076 return r; 077 } 078 079 private R(String pathToR) throws Exception { 080 rProcess = Runtime.getRuntime().exec(pathToR + " --no-save --no-readline"); 081 output = new BufferedWriter(new OutputStreamWriter(rProcess.getOutputStream())); 082 input = new BufferedReader(new InputStreamReader(rProcess.getInputStream())); 083 error = new BufferedReader(new InputStreamReader(rProcess.getErrorStream())); 084 String startMessage = getFromR(); 085 if (startMessage != null && startMessage.length() > 0) { 086 running = true; 087 return; 088 } 089 throw new Exception("could not start R"); 090 } 091 092 private synchronized String getFromR() throws Exception { 093 boolean lfSeen = false; 094 StringBuilder sb = new StringBuilder(); 095 096 for (int i = 0; i < MAXPOLLS; i++) { 097 if (!input.ready()) { 098 Thread.sleep(POLLINTERVAL); 099 } else { 100 break; 101 } 102 } 103 104 while (input.ready()) { 105 106 char c = (char) input.read(); 107 sb.append(c); 108 109 if (lfSeen) { 110 if (c == '>') { 111 return sb.toString(); 112 } else { 113 lfSeen = false; 114 } 115 } 116 if (c == '\n') { 117 lfSeen = true; 118 } 119 120 } 121 return sb.toString(); 122 } 123 124 public String execute(String command) throws Exception { 125 sendToR(command); 126 String cur = ""; 127 String last = ""; 128 129 cur = getFromR(); 130 131 while (cur != null && cur.length() > 0) { 132 last = cur; 133 cur = getFromR(); 134 } 135 136 return last; 137 } 138 139 public synchronized void shutdown() throws Exception { 140 r = null; 141 sendToR("q()"); 142 rProcess.waitFor(); 143 output.close(); 144 input.close(); 145 } 146 147 private synchronized void sendToR(String command) throws Exception { 148 if (r != null) { 149 try { 150 if (!command.endsWith("\n")) { 151 command += "\n"; 152 } 153 output.write(command, 0, command.length()); 154 output.flush(); 155 } catch (IOException e) { 156 shutdown(); 157 } 158 } 159 } 160 161 public void setMatrix(String label, Matrix matrix) throws Exception { 162 execute(label + " <- " + matrix.exportToString(FileFormat.R)); 163 } 164 165 private static String findR() { 166 if (pathToR == null) { 167 File file = null; 168 for (String s : SEARCH) { 169 if (s != null) { 170 file = new File(s); 171 if (file.exists()) { 172 pathToR = file.getAbsolutePath(); 173 return pathToR; 174 } 175 } 176 } 177 } 178 return pathToR; 179 } 180 181 public Matrix getMatrix(String label) throws Exception { 182 try { 183 184 String rawRows = execute("cat(nrow(" + label + "))"); 185 String rString = rawRows.split("\n")[1].replaceAll("\\>", "").trim(); 186 int rows = Integer.parseInt(rString); 187 String rawCols = execute("cat(ncol(" + label + "))"); 188 String cString = rawCols.split("\n")[1].replaceAll("\\>", "").trim(); 189 int cols = Integer.parseInt(cString); 190 191 String rawText = execute("cat(" + label + ")"); 192 String[] rawValues = rawText.split("\n")[1].split("[\\s]+"); 193 194 Matrix matrix = Matrix.factory.zeros(rows, cols); 195 196 int i = 0; 197 for (int r = 0; r < rows; r++) { 198 for (int c = 0; c < cols; c++) { 199 matrix.setAsDouble(Double.parseDouble(rawValues[i++].replaceAll("\\>", "") 200 .trim()), r, c); 201 } 202 } 203 204 return matrix; 205 } catch (Exception e) { 206 e.printStackTrace(); 207 return null; 208 } 209 } 210 211 public static boolean isAvailable() { 212 return findR() != null; 213 } 214 215 public static String toString(String[] strings) { 216 if (strings.length != 0) { 217 return "," + strings[0]; 218 } else { 219 return ""; 220 } 221 } 222 223 public void plot(Matrix matrix, String... format) throws Exception { 224 execute("X11()"); 225 setMatrix("ujmpmatrix", matrix); 226 execute("plot(ujmpmatrix" + toString(format) + ")"); 227 } 228 229 public void pairs(Matrix matrix, String... format) throws Exception { 230 execute("X11()"); 231 setMatrix("ujmpmatrix", matrix); 232 execute("pairs(ujmpmatrix" + toString(format) + ")"); 233 } 234 235 public void qqnorm(Matrix matrix, String... format) throws Exception { 236 execute("X11()"); 237 setMatrix("ujmpmatrix", matrix); 238 execute("qqnorm(ujmpmatrix" + toString(format) + ")"); 239 } 240 241 public void hist(Matrix matrix, String... format) throws Exception { 242 execute("X11()"); 243 setMatrix("ujmpmatrix", matrix); 244 execute("hist(ujmpmatrix" + toString(format) + ")"); 245 } 246 247 public void image(Matrix matrix, String... format) throws Exception { 248 execute("X11()"); 249 setMatrix("ujmpmatrix", matrix); 250 execute("image(ujmpmatrix" + toString(format) + ")"); 251 } 252 253 public void boxplot(Matrix matrix, String... format) throws Exception { 254 execute("X11()"); 255 setMatrix("ujmpmatrix", matrix); 256 execute("boxplot(ujmpmatrix" + toString(format) + ")"); 257 } 258 259 public void closeLastFigure() throws Exception { 260 execute("dev.off()"); 261 } 262 263 }