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.InputStreamReader;
030    import java.io.OutputStreamWriter;
031    
032    import org.ujmp.core.Matrix;
033    import org.ujmp.core.enums.FileFormat;
034    
035    public class Matlab {
036    
037            public static String[] SEARCH = new String[] {};
038    
039            static {
040                    try {
041                            SEARCH = new String[] { System.getProperty("Matlab"),
042                                            System.getProperty("user.home") + "/matlab/bin/matlab", "/usr/bin/matlab",
043                                            "/opt/matlab/bin/matlab" };
044                    } catch (Exception e) {
045                    }
046            }
047    
048            public static final String MATLABPARAMETERS = "-nosplash -nojvm";
049    
050            private static String pathToMatlab = null;
051    
052            private BufferedReader input = null;
053    
054            private BufferedWriter output = null;
055    
056            private BufferedReader error = null;
057    
058            private Process matlabProcess = null;
059    
060            private boolean running = false;
061    
062            private static Matlab matlab = null;
063    
064            public static synchronized Matlab getInstance() throws Exception {
065                    if (matlab == null) {
066                            matlab = getInstance(findMatlab());
067                    }
068                    return matlab;
069            }
070    
071            private static String findMatlab() {
072                    if (pathToMatlab == null) {
073                            File file = null;
074                            for (String s : SEARCH) {
075                                    if (s != null) {
076                                            file = new File(s);
077                                            if (file.exists()) {
078                                                    pathToMatlab = file.getAbsolutePath();
079                                                    return pathToMatlab;
080                                            }
081                                    }
082                            }
083                    }
084                    return pathToMatlab;
085            }
086    
087            public static synchronized Matlab getInstance(String pathToMatlab) throws Exception {
088                    if (matlab == null) {
089                            matlab = new Matlab(pathToMatlab);
090                    }
091                    return matlab;
092            }
093    
094            private Matlab(String pathToMatlab) throws Exception {
095                    matlabProcess = Runtime.getRuntime().exec(pathToMatlab + " " + MATLABPARAMETERS);
096                    output = new BufferedWriter(new OutputStreamWriter(matlabProcess.getOutputStream()));
097                    input = new BufferedReader(new InputStreamReader(matlabProcess.getInputStream()));
098                    error = new BufferedReader(new InputStreamReader(matlabProcess.getErrorStream()));
099                    String startMessage = getFromMatlab();
100                    if (startMessage != null && startMessage.length() > 0) {
101                            running = true;
102                            return;
103                    }
104                    throw new Exception("could not start Matlab");
105            }
106    
107            private synchronized String getFromMatlab() throws Exception {
108                    boolean endSeen = false;
109                    StringBuilder sb = new StringBuilder();
110    
111                    while (true) {
112                            while (!input.ready()) {
113                                    Thread.yield();
114                            }
115                            while (input.ready()) {
116    
117                                    char c = (char) input.read();
118                                    sb.append(c);
119    
120                                    if (c == '>') {
121                                            if (endSeen) {
122                                                    return sb.substring(0, sb.length() - 2);
123                                            }
124                                            endSeen = true;
125                                    } else {
126                                            endSeen = false;
127                                    }
128                            }
129                    }
130            }
131    
132            public String execute(String command) throws Exception {
133                    sendToMatlab(command);
134                    return getFromMatlab();
135            }
136    
137            public synchronized void shutdown() throws Exception {
138                    sendToMatlab("exit");
139                    matlabProcess.waitFor();
140                    output.close();
141                    input.close();
142            }
143    
144            private synchronized void sendToMatlab(String command) throws Exception {
145                    if (!command.endsWith("\n")) {
146                            command = command + "\n";
147                    }
148                    output.write(command, 0, command.length());
149                    output.flush();
150            }
151    
152            public void setMatrix(String label, Matrix matrix) throws Exception {
153                    execute(label + "=" + matrix.exportToString(FileFormat.M));
154            }
155    
156            public Matrix getMatrix(String label) throws Exception {
157                    try {
158                            String rawRows = execute("fprintf(1,'%d\\n',size(" + label + ",1));");
159                            int rows = Integer.parseInt(rawRows.trim());
160                            String rawCols = execute("fprintf(1,'%d\\n',size(" + label + ",2));");
161                            int cols = Integer.parseInt(rawCols.trim());
162    
163                            String rawText = execute("fprintf(1,'%55.55f\\n'," + label + ")");
164                            String[] rawValues = rawText.split("\n");
165    
166                            Matrix matrix = Matrix.factory.zeros(rows, cols);
167    
168                            int i = 0;
169                            for (int c = 0; c < cols; c++) {
170                                    for (int r = 0; r < rows; r++) {
171                                            matrix.setAsDouble(Double.parseDouble(rawValues[i++]), r, c);
172                                    }
173                            }
174    
175                            return matrix;
176                    } catch (Exception e) {
177                            e.printStackTrace();
178                            return null;
179                    }
180            }
181    
182            public static boolean isAvailable() {
183                    return findMatlab() != null;
184            }
185    
186            public void plot(Matrix matrix, String... format) throws Exception {
187                    setMatrix("ujmpmatrix", matrix);
188                    execute("figure;");
189                    execute("plot(ujmpmatrix" + toString(format) + ");");
190            }
191    
192            public void hist(Matrix matrix, String... format) throws Exception {
193                    setMatrix("ujmpmatrix", matrix);
194                    execute("figure;");
195                    execute("hist(ujmpmatrix" + toString(format) + ");");
196            }
197    
198            public void surf(Matrix matrix, String... format) throws Exception {
199                    setMatrix("ujmpmatrix", matrix);
200                    execute("figure;");
201                    execute("surf(ujmpmatrix" + toString(format) + ");");
202            }
203    
204            public void imagesc(Matrix matrix, String... format) throws Exception {
205                    setMatrix("ujmpmatrix", matrix);
206                    execute("figure;");
207                    execute("imagesc(ujmpmatrix" + toString(format) + ");");
208            }
209    
210            public void bar(Matrix matrix, String... format) throws Exception {
211                    setMatrix("ujmpmatrix", matrix);
212                    execute("figure;");
213                    execute("bar(ujmpmatrix" + toString(format) + ");");
214            }
215    
216            public void errorbar(Matrix x, Matrix y, Matrix e, String... format) throws Exception {
217                    setMatrix("ujmpmatrix_x", x);
218                    setMatrix("ujmpmatrix_y", y);
219                    setMatrix("ujmpmatrix_e", e);
220                    execute("figure;");
221                    execute("errorbar(ujmpmatrix_x,ujmpmatrix_y,ujmpmatrix_e" + toString(format) + ");");
222            }
223    
224            public void barh(Matrix matrix, String... format) throws Exception {
225                    setMatrix("ujmpmatrix", matrix);
226                    execute("figure;");
227                    execute("barh(ujmpmatrix" + toString(format) + ");");
228            }
229    
230            public void stem(Matrix matrix, String... format) throws Exception {
231                    setMatrix("ujmpmatrix", matrix);
232                    execute("figure;");
233                    execute("stem(ujmpmatrix" + toString(format) + ");");
234            }
235    
236            public void pie(Matrix matrix, String... format) throws Exception {
237                    setMatrix("ujmpmatrix", matrix);
238                    execute("figure;");
239                    execute("pie(ujmpmatrix" + toString(format) + ");");
240            }
241    
242            public void pie3(Matrix matrix, String... format) throws Exception {
243                    setMatrix("ujmpmatrix", matrix);
244                    execute("figure;");
245                    execute("pie3(ujmpmatrix" + toString(format) + ");");
246            }
247    
248            public void plotmatrix(Matrix matrix, String... format) throws Exception {
249                    setMatrix("ujmpmatrix", matrix);
250                    execute("figure;");
251                    execute("plotmatrix(ujmpmatrix" + toString(format) + ");");
252            }
253    
254            public void plot(Matrix x, Matrix y, String... format) throws Exception {
255                    setMatrix("ujmpmatrix_x", x);
256                    setMatrix("ujmpmatrix_y", y);
257                    execute("figure;");
258                    execute("plot(ujmpmatrix_x,ujmpmatrix_y" + toString(format) + ");");
259            }
260    
261            public static String toString(String[] strings) {
262                    if (strings.length != 0) {
263                            return ",'" + strings[0] + "'";
264                    } else {
265                            return "";
266                    }
267            }
268    }