A nice and easy-to-use static java wrapper for matplotlib.pyplot
Static means the generated plot window runs on a python process, hence it cannot be dynamically included in a Java GUI such as JPanel or JFrame.
The plotting library of matplotlib is one the most powerful and easy to use libraries ever created. Although it is possible to implement a similar library purely in java, it also makes sense to simply use the capabilities of the matplotlib. To this end, this repository aims at providing a java framework that can easily generate the python code necessary for drawing the plots. After the python code is generated, the framework will execute a terminal (commandline) command "python file_name.py" and a window will open with the drawn plots.
The original documentation of matplotlib can be found here: Matplotlib Documentation
REQUIREMENTS: this framework requires the installation of python 2 or python 3 and the matplotlib and numpy packages.
- XYPlot
- this is similar to executing plt.plot(x, y, *args, **kwargs) in python. XYPlot resembles a Figure object in matplotlib.
- XYSubPlot
- this is similar to executing plt.subplot(row, column, index) first and then plt.plot(x, y, *args, **kwargs) in matplotlib.
- PolarPlot
- this is similar to executing a plot with projection='polar' keyword argument.
- ContourPlot
- this is similar to executing plt.contour(X, Y, Z, labels=[]). The contour labels can be set in a similar way to plt.clabel(**kwargs). An interface called "MeshGrid.java" is provided to generate the Z data points.
public interface MeshGrid { double value(double x, double y) ; }
- ContourSubPlot
- this is similar to having multiple subplots each one drawing contour plots.
As the name suggests, this provides a simple API to draw plots in XY cartesian coordinates. The step-by-step guide is as follows (see Example1.java):
- Step 0: create some data. Let's plot y=sin(x) and y=cos(x) over the [-2pi, 2pi] interval.
// step 0
double[] x = MathUtils.linspace(-2.0*Math.PI, 2.0*Math.PI, 1000) ;
double[] y1 = Arrays.stream(x).map(Math::sin).toArray() ;
double[] y2 = Arrays.stream(x).map(Math::cos).toArray() ;
- Step 1: create an XYPlot instance and plot the first curve y=sin(x). The java code is based on the builder design pattern which means it is possible to change multiple commands one after another. The "plot()" method returns an XYSeries object which is used to set properties such as "marker", "color", "linestyle", etc.
// step 1
XYPlot plt = new XYPlot("A simple plot from java!!!!") ;
plt.plot(x, y1).color("b").linestyle("-").linewidth(2.0).label("y=sin(x)") ;
- Step 2: now plot the second curve y=cos(x) by invoking the "plot()" method on the same XYPlot. This returns a new XYSeries which can be configured for this curve.
// step 2
plt.plot(x, y2).color("r").linestyle("--").linewidth(2.0).label("y=cos(x)") ;
- Step 3: now that we're done with the curves, let's configure the plot itself. Let's add xlabel and ylabel, make the legend and grids visible, also ask the plot to use tight_layout() to automatically calculate the best dimesions.
// step 3
plt.xlabel("X values").ylabel("Y values").legend(true).grid(true) ;
plt.tightLayout() ;
- Step 4: finally, we can either "show()" the plot or save it a file "savefig(file_name)".
// step 4
plt.show();
Here's the result:
Simplar steps can be taken to create subplots of multiple figures. See Example2.java for more details.
Here's an example:
// step 0
double[] x = MathUtils.linspace(-2.0*Math.PI, 2.0*Math.PI, 1000) ;
double[] y1 = Arrays.stream(x).map(Math::sin).toArray() ;
double[] y2 = Arrays.stream(x).map(Math::cos).toArray() ;
double[] y3 = Arrays.stream(x).map(t -> t*Math.sin(t)).
8084
toArray() ;
double[] y4 = Arrays.stream(x).map(t -> t*Math.cos(t)).toArray() ;
// step 1
XYSubPlot plt = new XYSubPlot() ;
plt.subplot(2, 2, 1).grid(true).xlabel("x values").ylabel("y1 values").title("first subplot!!")
.legend(true)
.plot(x, y1).color("b").linestyle("-").linewidth(2.0).label("y=sin(x)") ;
// step 2
XYPlot subplot = plt.subplot(2, 2, 3).grid(false).xlabel("x values").ylabel("y2 values").title("second subplot!!").legend(true) ;
subplot.plot(x, y2).color("r").linestyle("--").linewidth(3.0).label("y=cos(x)") ;
subplot.plot(x, y3).color("b").linestyle("-").linewidth(2.0).label("y=x*sin(x)") ;
// step 3
plt.subplot(1, 2, 2).plot(x, y4).color("g").linestyle("-").linewidth(3.0).label("y=x*cos(x)") ;
// step 4
plt.tightLayout() ;
plt.show();
This plot is very similar to XYPlot, except it uses plt.subplot(1, 1, 1, polar=True) command to generate a polar plot. Note that the order of parameters is theta and r.
See Exampe3.java for more info.
// step 0
double[] theta = MathUtils.linspace(-2.0*Math.PI, 2.0*Math.PI, 1000) ;
double[] r1 = Arrays.stream(theta).map(t -> abs(sin(t))).toArray() ;
double[] r2 = Arrays.stream(theta).map(t -> abs(cos(t))).toArray() ;
// step 1
PolarPlot plt = new PolarPlot("A polar plot from java!!!!") ;
plt.plot(theta, r1).color("b").linestyle("-").linewidth(2.0).label("y=sin(x)") ;
// step 2
plt.plot(theta, r2).color("r").linestyle("--").linewidth(3.0).label("y=cos(x)") ;
// step 3
plt.tightLayout() ;
// step 4
plt.show();
Here's the result:
The contour plot can draw contours (unfilled or filled) of a two-dimensional function using plt.contour(X,Y,Z) or plt.contourf(X,Y,Z). The contour levels can be set automatically, or passing them as a parameter, or by clicking on the drawn contours (manual mode). Let's plot the contours z=sin(x)cos(y) over the [-2pi,2pi]x[-pi,pi] region.
- Step 1: create the x, y data.
// step 1
double[] x = MathUtils.linspace(-2.0*PI, 2.0*PI, 200) ;
double[] y = MathUtils.linspace(-PI, PI, 100) ;
- Step 2: create z data using MeshGrid interface.
- Note that we don't need to calculate the z values. We just pass the meshgrid function to the plot.
// step 2
MeshGrid grid = (xi, yj) -> sin(xi)*cos(yj) ;
- Step 3: create the contour plot and specify the contour levels
// step 3
ContourPlot plt = new ContourPlot("A contour plot from java!!!") ;
plt.contour(x, y, grid)
.clabel().levels(MathUtils.linspace(-1.0, 1.0, 15))
.color("r").fmt("%.2f");
- Step 4: add xlabel, ylabel and turn the grid on.
// step 4
plt.xlabel("x values").ylabel("y values").grid(true, "major", "both") ;
- Step 5: finally, show the plot or save it to a file.
// step 5
plt.show();
Here's the result: