Once again I would like to welcome guest blogger Malcolm Lidierth of King’s College London, who has already written here in the past. Today Malcolm will explain the basics of using Groovy code within Matlab.
Readers of this blog are likely to be familiar with calling Java from within Matlab code and/or writing custom Java code for Matlab use. But, Java is only one of many programming languages that can use the Java Virtual Machine. Here, I’d like to draw Matlab-users’ attention to another: Groovy.
Groovy is a superset of Java that compiles to Java byte-code and seamlessly integrates with existing Java code. So seamlessly, in fact, that you can mix-and-match Java and Groovy syntax in a single file or method. This means that you can call Groovy classes from Matlab just as though they were Java classes: Matlab will see no difference.
Most IDEs support Groovy and include the necessary files – IntelliJ seems particularly good for Groovy development. Groovy is also available separately at http://groovy.codehaus.org/Download. Use Groovy 1.8.6 or earlier, not the latest 2.0 version (* see below).
All that is needed to run Groovy in Matlab is to include its jar files on your Matlab javaclasspath, by using Matlab’s javaaddpath function to add to the dynamic classpath, or by adding the jar locations to the classpath.txt file (the static classpath, which is generally better).
To illustrate a few of its features, below is a rough-and-ready static method in Groovy to return a factorial:
package Examples class StaticLib { static factorial(n){ def fact=1.0 for (def k=1; k< =n; k++) fact*=k return fact } } |
Java programmers will note there are no public
keywords: in Groovy public is the default. Next the method declaration has no return type. Neither does the input n
. In Groovy, typing is optional. This is exploited on the next line, where fact
is declared using the def
keyword. Groovy will determine its type at runtime much as Matlab does for variables. The same is true for the loop control variable k
.
To run the code at the Matlab command prompt, use commands as you would for Java e.g:
>> import Examples.StaticLib >> StaticLib.factorial(40) >> StaticLib.factorial(int64(40)) >> StaticLib.factorial(java.math.BigInteger(40)) |
all produce:
ans = 815915283247897734345611269596115894272000000000.0 |
This is an exact, and correct, result because Groovy instantiated fact
as a java.math.BigDecimal
when it was initialized with a floating-point value. Note also, that Groovy’s dynamic typing meant only one method was needed– not one for every possible class of input. With Groovy, you need to write much less code. (Caution: running this code with very large n will work, but slowly, and potentially take up all available memory to store the result).
The small typing change below makes a substantial difference to the code’s operation:
package Examples class NewLib { def factorial = {n -> def fact = 1.0 for (def k = 1; k < = n; k++) fact *= k return fact } } |
Here, factorial is a property, not a method, of the class and its contents are the code – in Groovy this is a closure (in Matlab it would be called an anonymous function).
Create an instance of the NewLib
class in Matlab, call the get method on the factorial
property and run the code in Matlab as follows:
>> myObj=Examples.NewLib(); >> func=myObj.getFactorial(); >> func.call(40) ans = 815915283247897734345611269596115894272000000000.0 |
Using Groovy saved a lot of work: there was no need to write a no argument constructor or a getFactorial() method. Groovy did that automatically.
Here is another code snippet where Groovy’s dynamic typing makes it look much more like Matlab than Java:
for (obj in props) { switch (obj.key) { … case "Alpha": case "EdgeColor": case "LineColor": case "XData": case "YData": case "ZData": plot.("set" + obj.key)(props.(obj.key)) break … } } |
props is a LinkedHashMap
. We start by running through each of the entries in this map in a loop using:
for (obj in props) |
Each entry is assigned to obj
in turn. Again, we let Groovy determine the class of obj
dynamically – it will be of class java.util.LinkedHashMap$Entry
, but we do not need to worry about that detail.
For each entry we retrieve the key and use that as the variable for the switch
block. In this case, the keys are all strings and, in Groovy, strings can be used in case
statements (Java 7 would be needed for that if the code were written in Java; note that Java 7 is still not integrated in Matlab as of this date).
Within the switch block, the code invokes a setter on an object called plot
. Rather than write separate lines for each possible property in the key list, one line is enough:
plot.("set" + obj.key)(props.(obj.key)) |
The key string is pre-pended with “set” and the corresponding method is invoked passing the value from the LinkedHashMap
entry as input – so a particular iteration of the loop, this might equate for example to plot.setAlpha(0.5)
For a Matlab programmer who is put off from delving into Java because of the tedious boiler-plate code it requires, Groovy may be an attractive alternative. Groovy also has many powerful features for handling regular expressions, a set of builder classes (for example a thread-safe SwingBuilder
class), writing domain specific languages and for meta-object programming including run-time injection of new methods. There is also a growing set of Groovy plugin modules.
Not all Java programmers like Groovy. The dynamic features inevitably create run-time overheads and mean that type-mismatches that would be detected at compile-time in Java may produce run-time exceptions with Groovy, but Groovy 2.0 addresses some of these issues by introducing new compiler annotations. My own use of it has been limited, partly because of these issues: I have used it to create a static library to link Matlab, R, SciLab etc to a graphics package written in Java. The dynamic features of Groovy have been useful there to reduce the work involved.
* Note: Groovy 2.0 was released 28.06.2012. Initial experiments suggest it does not work within Matlab, perhaps because of version clashes with jars on the Matlab static class path.
—————————-
- Aug 21 – Matlab performance tuning
- Aug 22 – Advanced Matlab GUI
- Aug 23 – Using Java in Matlab (inc. extra advanced GUI)
Anyone interested please email me (altmany at gmail dot com) for more details.
Nice article.
It looks like Groovy 2.0 was implemented to take advantage of enhancements in Java 7 while MATLAB through R2012a uses Java 6. This may be why there is trouble using Groovy 2.0 with MATLAB.
@Donn
There are two sets of jars for Groovy: the “indy” set is for the Java 7 feature users. AFAIK, the standard set should be OK back to Java 5.
Note: Comments above about Groovy 2 no longer apply. MATLAB works fine with 2.0.5 – the latest release at the time of writing. The change occurred with 2.02 or 03.
I’m trying Groovy 2.4.6 in Matlab R2015b and everything looks fine until I try to create an instance of a class that was parsed dynamically.
Example:
What could be the problem?
The code is fine and works in an external GroovyConsole session so the problem is running it within MATLAB.
Tracking down the problem would likely be difficult and time-consuming.
I’d probably start by swapping to an earlier groovy version.
Then maybe by swapping to the latest JRE 8 release for MATLAB because it’s relatively simple to do and might (but only might) work. There are known issues with some earlier releases of Java 7 and groovy.
If not, a clash between versions of dependencies within groovy and the jars bundled with MATLAB might be the issue.
Update:
A quick check with JRE8 shows it does not fix the issue.
Groovy now uses Grape for dependency management:
http://docs.groovy-lang.org/latest/html/documentation/grape.html
I have found a relatively simple solution.
If this is an issue with dependencies, we might fix the problem by installing groovy-all-2.4.6.jar at MATLAB startup.
On MATLAB R2016a (on Mac El Capitan for the test) this works if we load either:
1. via a javaclasspath.txt file or
2. by editing classpath.txt
Yair has written about this here.
So, adding Groovy on MATLAB’s static javaclasspath rather than the dynamic path resolves the problem.
An issue may remain with the resolution of dependent jars. If Groovy and MATLAB ship with different versions of a jar file, which gets loaded and which will get used?
Adding Groovy as the first entry in classpath.txt is probably the most robust – but the least attractive – solution. I’d suggest using a javaclasspath.txt file and only editing classpath.txt if problems arise.
Note that if a newer jar file is being loaded and used via Groovy there could be knock-on effects for any code running in the JVM. You will be using a jar file that TMWs production tests have not been run against.
The fix above works on Windows too but an attempt by the Java runtime to add a key to the Windows registry when Groovy is first launched may give a warning.
Adding the key manually following http://www-01.ibm.com/support/docview.wss?uid=swg21496098 solved that for me (Windows 10 with R2016a).