Last week, guest blogger Malcolm Lidierth wrote about the open-source Waterloo graphics package and how it can be used in Matlab. Today, Malcolm continues the discussion of Waterloo with a set of examples in Matlab code.
Note: I highly recommend checking out Malcolm’s other open-source submissions/utilities on the Matlab File Exchange.
The Waterloo graphics routines provide three potential APIs for MATLAB-users:
- A Java API for the core code provides a simple and consistent mechanism for creating plots using the same data model for each of them, from line and scatter through quiver and contour plots.
- A Groovy API that can be used to call the Java API via some static methods that use Groovy’s dynamic typing mechanisms and so allows the same code to be called with different classes on input from different environments – a cell array from MATLAB for example.
- A Matlab API that mimics the standard MATLAB graphics routines and variously calls the Java-API and Groovy API as required.
I will concentrate here on the Matlab API, which is likely to be of more interest to the majority of readers. This uses Matlab OOP wrappers for the underlying Java objects and all provide access to them by using the getObject() method on the wrappers, so Matlab and Java code can be easily mixed.
Simple Waterloo plots
To create a Matlab figure that can accept Waterloo graphics call GXFigure instead of figure e.g.
f = GXFigure(10);
creates figure 10 and enables it for Waterloo.
In Matlab, you might use gca to create a figure and a set of axes – for Waterloo use gxgca instead. The graph reference also needs to be provided as input to force Matlab to use the Waterloo plotting methods. So
in Matlab becomes:
Here are the outputs:
Note that gxgca returns gca if the current axes are not Waterloo-enabled (so its use above would have produced a Matlab scatter plot in that case). If there is no current axes object, it creates a Waterloo
GXGraphand returns a reference to it (just as gca creates Matlab axes when there are none).
However, Waterloo does not attempt to completely mimic Matlab: the markers above were specified as ‘^r’. A full LineSpec (e.g., ‘-^r’) would produce an error when given to the scatter function in Matlab, but Waterloo does not care – if a property is specified that is inappropriate it will be ignored. That is because the Matlab properties are translated into a set of Java properties that all plots have in common, but not all plots use. Note also, that hold is effectively ‘on’ for Waterloo, markers are filled and grids are drawn by default (but all the defaults are user-editable).
Combining Waterloo plots
Waterloo plots can be added together. To draw a line through a set of scatter points, a line plot is added to it. Similarly, an error bar plot can be added to that. The Waterloo Matlab-API has an errorbar function that does that. As the plots are additive the process can be continued to create a series of such compound plots:
f = GXFigure(); ax = subplot(f,1,1,1); set(gcf, 'Units', 'normalized', 'Position', [0.1 0.1 0.8 0.8], 'Name', 'TestError'); x = 0.5 : 0.5 : 10; y = log(x); a1 = errorbar(ax, x, y, y/3.5, 'LineSpec', '-ob'); errorbar(a1, , y*2, y/3.5*2,'LineSpec', '-sg'); errorbar(a1, , y*5, y/3.5*5, 'LineSpec', '-dr'); Y = errorbar(a1, , y*10, y/3.5*10, 'LineSpec', '-^m'); ax.getObject().getView().autoScale();
Here I have created a GXFigure, used its subplot method to create a graph, plotted the first errorbar series to it and parented the remaining plots from the first. As they share their x-data, that is specified as empty for the last three plots.
The final line above looks less Matlab-like. For
axis the Matlab OOP wrapper created by subplot – it’s a
- ax.getObject() returns the Java Swing container which has a “view” (which is the graph)
- ax.getObject().getView() returns the graph
ax.getObject().getView().autoScale() just causes the graph to be auto-scaled to fit in all the graphics. The axes can be moved, expanded and shrunk using the mouse and double-clicking displays a GUI editor as shown last week. Clicking on a plot causes the plot to become the current Waterloo graphic object, which can then be accessed with gxgco instead of gco (just as gxgca was used in place of gca).
Combining Matlab and Waterloo sub-plots
I have shown only single-axes plots till now. The subplot function can, as in Matlab, create multiple axes and these can be used to mix Waterloo and Matlab graphics in a single figure as here (upper-left and lower-right are Matlab):
Some additional examples
Here then are a few more plot examples:
f = GXFigure(); set(f.Parent, 'Units', 'normalized', 'Position', [.2 .2 .6 .6], 'Name', 'TestQuiver'); [X,Y] = meshgrid(-2:.2:2); Z = X.*exp(-X.^2 - Y.^2); [DX,DY] = gradient(Z,.2,.2); ax = subplot(gxgcf,1,1,1); q1 = quiver(ax,X,Y,DX,DY, 0.9);
f = GXFigure(); set(gcf, 'Units', 'normalized', 'Position', [0.1 0.1 0.8 0.8], 'Name', 'TestStairs'); x = linspace(-2*pi,2*pi,40); y = sin(x); ax = subplot(f, 1, 2, 1); a1 = stairs(gxgca, x, y, 'LineColor', 'r'); b1 = stairs(gxgca, x, y*2,'LineColor', 'g'); c1 = stairs(gxgca, x, y*5,'LineColor', 'm'); d1 = stairs(gxgca, x, y*10,'LineColor', 'b');
load penny; f = GXFigure(); ax = subplot(f,1,1,1); ax.getObject().setAspectRatio(1); % This sets the aspect ratio of the view in the container p2 = contour(ax, flipud(P), 30);
I have added labels and titles here using the GUI editor – they can of course also be set programmatically.
Waterloo is far from finished and more plot types are being added. Here is a taster of a filled contour plot which will be available in the next update (see the development version GIT repository):
f = GXFigure(); set(gcf, 'Name', 'TestContour', 'Units', 'normalized', 'Position', [0.2 0.2 0.7 0.5]) ax = subplot(f,1,1,1); ax.getObject().setAspectRatio(1); p1 = contourf(ax, peaks(100), 20); p1.getObject().setAlpha(0.3);
If you have any comments or feedback on Waterloo, please feel free to join its open-source development effort, or simply leave a comment below.