Once again I welcome guest blogger Joshua Kaplan for his continued series on MatlabControl – the Java-to-Matlab Interface (JMI) wrapper
Last week I introduced a Java package called matlabcontrol which can be used to access Matlab from Java.
Let’s now put matlabcontrol to work from Java. Below is a very simple Java class called LocalExample which uses Swing to create a window (JFrame), a text field (JTextField), and a button (JButton). When the button is pressed, the text in the field will be evaluated in Matlab using LocalMatlabProxy.eval(…), which was explained in the previous post.
import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextField; import matlabcontrol.LocalMatlabProxy; import matlabcontrol.MatlabInvocationException; /** * A simple demo of some of matlabcontrol's functionality. * * @author Joshua Kaplan */ public class LocalExample extends JFrame { /** * Constructs this example and displays it. */ public LocalExample() { //Window title super("Local Session Example"); //Panel to hold field and button JPanel panel = new JPanel(); this.add(panel); //Input field final JTextField inputField = new JTextField(); inputField.setColumns(15); panel.add(inputField); //Eval button JButton evalButton = new JButton("eval"); panel.add(evalButton); //Eval runnable, to execute in separate (non-EDT) thread final ExecutorService executor = Executors.newSingleThreadExecutor(); final Runnable evalRunnable = new Runnable() { public void run() { try { LocalMatlabProxy.eval(inputField.getText()); } catch (MatlabInvocationException exc) { } } }; //Eval action event for button and field ActionListener evalAction = new ActionListener() { public void actionPerformed(ActionEvent e) { //This uses the EDT thread, which may hang Matlab... //LocalMatlabProxy.eval(inputField.getText()); //Execute runnable on a separate (non-EDT) thread executor.execute(evalRunnable); } }; evalButton.addActionListener(evalAction); inputField.addActionListener(evalAction); //On closing, release resources of this frame this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { LocalExample.this.dispose(); } }); //Display this.pack(); this.setResizable(false); this.setVisible(true); } } |
We can either copy and compile the above code (remember to import the matlabcontrol JAR file in your compiler; four class files will be created), or download the already-compiled code here. Note that the already-compiled classes were compiled using JDK 1.6, so if you have Matlab R2007a (7.4) or earlier you will need to compile using an earlier Java compiler.
We now need to tell Matlab where to find both the matlabcontrol JAR file, and our LocalExample class files. We can either add the files to the static java classpath (by editing the classpath.txt file), or add them only to the current Matlab session’s dynamic classpath:
% Add Java files to current Matlab session's dynamic classpath javaaddpath LocalExample.zip javaaddpath matlabcontrol-3.01.jar |
To run the Java program, simply type LocalExample in the Matlab Command Window – A small Java window will appear and JMI will evaluate any expression typed into it:
>> LocalExample ans = LocalExample[frame0,0,0,202x67,title=Local Session Example,...] |
a =
1.77245385090552 |
When we called LocalMatlabControl.eval(…) from the Command Window last week, what occurred behind the scenes was actually quite different from what happens when we press the “eval” button in the Java program. This is because in the Command Window everything executes in Matlab’s single main thread. When we pressed “eval”, the code executed from the Event Dispatch Thread (EDT), which is a separate thread.
EDT is used extensively by Matlab when accessing graphical components such as a figure window, uicontrols or plots. When calling a function from JMI, the calling thread always blocks (pauses) until Matlab is done completing whatever has been asked of it. So, if we called JMI/matlabcontrol from the EDT and Matlab needed to use the EDT, then everything will lock up. To fix this potential problem, when you press the “eval” button the command is sent off to a separate thread which can block without preventing Matlab from doing its work. Future versions of matlabcontrol will try to simplify this process further. matlabcontrol over a remote connection, the topic of my next post, does not suffer from this complication because Matlab and your program are not sharing the same EDT or even the same Java runtime process (JVM).
While the above Java example is quite simple, using a combination of all of the methods described throughout my previous post, a much more sophisticated program can be created. To explore the methods in more detail you can use the demo available here (downloadable JAR). The demo uses a remote connection to Matlab, but the available methods are the same. In my next and final article on this subject, I will explore controlling Matlab using matlabcontrol over a remote connection.
I am looking forward to your blog post about controlling Matlab using matlabcontrol over a remote connection. Thanks for all the effort you put into matlabcontrol!
[…] Last week I demonstrated using matlabcontrol to call Matlab from Java from within the Matlab application. Today I will explain how to control Matlab from a remote Java session. […]
hello guys.
Where should I found this file?
import matlabcontrol.LocalMatlabProxy;
import matlabcontrol.MatlabInvocationException;
matlabcontrol.jar is available here: http://code.google.com/p/matlabcontrol/downloads/list
I have been following your posts with interest. Here is a question. I have very large data sets in MATLAB and would like to use a custom table model to display them in java. I tested the process in pure java and it works as it should.
Now to implement an AbstractTableModel I need to be able to call Matlab (or possibly C), to get the correct values on getColumnCount , getRowCount and getValueAt
Using the JMI I can get the data with a call to my own Matlab function mat.fevalConsoleOutput(“cinguj”, …);
But when this is called by SWING I cannot use Matlab.mtFevalConsoleOutput because swing is not on the main Matlab Thread so JMI complains and fevalConsoleOutput seems to run asynchronously so that I do not get the right answer in time.
Matlabcontrol does not call fevalConsoleOutput and thus does not address the issue. I also tried implementing the com.mathworks.jmi.CompletionObserver (just say implements CompletionObserver and add a completed method) but I have not found out to get the java to wait until completion (things I have tried locked up).
Yair, if you don’t have an easy answer, I am willing to invest some money into it.
Hi, I tried to compile this example, and this is what I get
# javac LocalExample.java
LocalExample.java:55: non-static method eval(java.lang.String) cannot be referenced from a static context
LocalMatlabProxy.eval(inputField.getText());
Any help will be appreciated. Thanks.
hi, can the matlabcontrol be used also for matlab runtime?
Hi
I am using calls of the form
mat= new com.mathworks.jmi.Matlab();
mat.fevalConsoleOutput(“function”,variables);
which works wonderfully on Matlab itself but am having a major bug when the same code is compiled (with the matlab compiler).
The bug occurs when the callback attempts to open graphic objects.
The stack trace differs depending on the OS and version but shows similar
I would like to debug matlab code using JMI… Localmatlabproxy.eval option
Pls let me know yair