JMI wrapper – local MatlabControl part 2

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,...]

Java window calling Matlab via JMI

Java window calling Matlab via JMI

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. 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.

Categories: Guest bloggers, High risk of breaking in future versions, Java, Undocumented feature

Tags: , , ,

Bookmark and SharePrint Print

8 Responses to JMI wrapper – local MatlabControl part 2

  1. ben says:

    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!

  2. Pingback: JMI wrapper – remote MatlabControl | Undocumented Matlab

  3. n n says:

    hello guys.
    Where should I found this file?

    import matlabcontrol.LocalMatlabProxy;
    import matlabcontrol.MatlabInvocationException;

  4. 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.

  5. Inno says:

    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.

  6. weikuiwang says:

    hi, can the matlabcontrol be used also for matlab runtime?

  7. 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

      [  0] 000000007AD33FB2                  mcr.dll+278450 (mcrInstance::MCallbackAttach+000018)
      [  1] 000000007D4840FD             libmwgui.dll+213245 (MCallback::init+000253)
      [  2] 000000007D4842B7             libmwgui.dll+213687 (MCallback::MCallback+000039)
      [  3] 000000007D4847DF             libmwgui.dll+215007 (CopyMCallback+000063)
      [  4] 00000000793CB4DD                   hg.dll+3060957 (gf_PixelPosition+009997)
      [  5] 00000000794C86A0                   hg.dll+4097696 (hgConvertUDInterfaceToHandle+013760)
      [  6] 000000007C4155E6                  udd.dll+284134 (UDInterface::setE+000806)
      [  7] 000000007C3DB1E4                  udd.dll+045540 (udiSet+000068)
    

Leave a Reply


Your email address will not be published. Required fields are marked *