Skip to content
Erich Seifert edited this page Sep 21, 2017 · 2 revisions

Styling plots, axes, and data series

The goal of this tutorial is to show how the appearance of a plots and its parts can be changed to fit your need. For this purpose, we will create a simple scatter plot and style its plot area, its data points, and its axes.

Creating a plot

First, we need some data plot. A simple point cloud with random data will do:

DataTable data = new DataTable(Double.class, Double.class, Double.class);

final int POINT_COUNT = 1000;
java.util.Random rand = new java.util.Random();
for (int i = 0; i < POINT_COUNT; i++) {
    double x = rand.nextGaussian();
    double y1 = rand.nextGaussian() + x;
    double y2 = rand.nextGaussian() - x;
    data.add(x, y1, y2);
}

Next, we need to create a new scatter plot which displays the data as two separate data series:

DataSeries series1 = new DataSeries("Series 1", data, 0, 1);
DataSeries series2 = new DataSeries("Series 2", data, 0, 2);
XYPlot plot = new XYPlot(series1, series2);

This is how our unstyled plot looks like:

https://eseifert.github.io/gral/tutorial/styling/unstyled.png

Styling the plot

In order to get enough space for axis labels to be displayed on the left and on the bottom we will add some space to the plot:

double insetsTop = 20.0,
       insetsLeft = 60.0,
       insetsBottom = 60.0,
       insetsRight = 40.0;
plot.setInsets(new Insets2D.Double(
    insetsTop, insetsLeft, insetsBottom, insetsRight));

Our plot still lacks a title which describes the plot's contents. So we simply add one by changing the text of the title:

plot.getTitle().setText("Nice scatter");

This is the result of styling the plot:

https://eseifert.github.io/gral/tutorial/styling/plot.png

Styling the plot area

The plot area is the largest area of the plot. It displays the plot's data points and the user should be able to view it easily. Therefore, we will change the color and width of the border around the plot area:

plot.getPlotArea().setBorderColor(new Color(0.0f, 0.2f, 0.8f));
plot.getPlotArea().setBorderStroke(new BasicStroke(2f));

This is the result of styling the plot area:

https://eseifert.github.io/gral/tutorial/styling/plot-area.png

Styling the data series

To see which point in the scatter plot belongs to which data series it would be nice to change the symbols and colors of all data points belonging to a certain series.

In out case we want all points of Series 1 to be displayed as semi-transparent blue circles. So we use the following code to change the settings of the corresponding PointRenderer:

PointRenderer points1 = new DefaultPointRenderer();
points1.setShape(new Ellipse2D.Double(-3.0, -3.0, 6.0, 6.0));
points1.setColor(new Color(0.0f, 0.3f, 1.0f, 0.3f));
plot.setPointRenderers(series1, points1);

We do the same for Series 2 and change it so that all its points are displayed as semi-transparent black rectangles:

PointRenderer points2 = new DefaultPointRenderer();
points2.setShape(new Rectangle2D.Double(-2.5, -2.5, 5.0, 5.0));
points2.setColor(new Color(0.0f, 0.0f, 0.0f, 0.3f));
plot.setPointRenderers(series2, points2);

This is the result of adjusting the point renderers:

https://eseifert.github.io/gral/tutorial/styling/points.png

Styling the axes

Finally, we will make the axes nicer. We'll give each axis a label, so it can be identified:

plot.getAxisRenderers(XYPlot.AXIS_X).get(0).setLabel("X");
plot.getAxisRenderers(XYPlot.AXIS_Y).get(0).setLabel("Y");

Although the default spacing of tick marks usually leads to good results, sometimes it needs to be adjusted. To get the correct spacing for each axis it is necessary to chage the TICKS_SPACING setting of the x and y axis to suitable values:

plot.getAxisRenderers(XYPlot.AXIS_X).get(0).setTickSpacing(1.0);
plot.getAxisRenderers(XYPlot.AXIS_Y).get(0).setTickSpacing(2.0);

Now, we will move the axes to the border of our plot area. To do this, we simply move the intersection point to most negative value that is allowed:

plot.getAxisRenderers(XYPlot.AXIS_X).get(0).setIntersection(-Double.MAX_VALUE);
plot.getAxisRenderers(XYPlot.AXIS_Y).get(0).setIntersection(-Double.MAX_VALUE);

This is the result of styling the axis renderers:

https://eseifert.github.io/gral/tutorial/styling/axes.png

Final code

Finally, here is the code for a displaying the plot in a Java Swing frame:

package tutorials.styling;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;

import javax.swing.JFrame;

import de.erichseifert.gral.data.DataSeries;
import de.erichseifert.gral.data.DataTable;
import de.erichseifert.gral.plots.BarPlot;
import de.erichseifert.gral.plots.PlotArea;
import de.erichseifert.gral.plots.XYPlot;
import de.erichseifert.gral.plots.axes.AxisRenderer;
import de.erichseifert.gral.plots.points.DefaultPointRenderer;
import de.erichseifert.gral.plots.points.PointRenderer;
import de.erichseifert.gral.ui.InteractivePanel;
import de.erichseifert.gral.util.Insets2D;

public class Styling extends JFrame {
    public Styling() {
        // Create data
        DataTable data = new DataTable(Double.class, Double.class, Double.class);

        final int POINT_COUNT = 1000;
        java.util.Random rand = new java.util.Random();
        for (int i = 0; i < POINT_COUNT; i++) {
            double x = rand.nextGaussian();
            double y1 = rand.nextGaussian() + x;
            double y2 = rand.nextGaussian() - x;
            data.add(x, y1, y2);
        }

        // Create series
        DataSeries series1 = new DataSeries("Series 1", data, 0, 1);
        DataSeries series2 = new DataSeries("Series 2", data, 0, 2);
        XYPlot plot = new XYPlot(series1, series2);

        // Style the plot
        double insetsTop = 20.0,
               insetsLeft = 60.0,
               insetsBottom = 60.0,
               insetsRight = 40.0;
        plot.setInsets(new Insets2D.Double(
                insetsTop, insetsLeft, insetsBottom, insetsRight));
        plot.getTitle().setText("Nice scatter");

        // Style the plot area
        plot.getPlotArea().setBorderColor(new Color(0.0f, 0.3f, 1.0f));
        plot.getPlotArea().setBorderStroke(PlotArea.BORDER, new BasicStroke(2f));

        // Style data series
        PointRenderer points1 = new DefaultPointRenderer();
        points1.setShape(new Ellipse2D.Double(-3.0, -3.0, 6.0, 6.0));
        points1.setColor(new Color(0.0f, 0.3f, 1.0f, 0.3f));
        plot.setPointRenderers(series1, points1);

        PointRenderer points2 = new DefaultPointRenderer();
        points2.setShape(new Rectangle2D.Double(-2.5, -2.5, 5, 5));
        points2.setColor(new Color(0.0f, 0.0f, 0.0f, 0.3f));
        plot.setPointRenderers(series2, points2);

        // Style axes
        plot.getAxisRenderers(XYPlot.AXIS_X).get(0).setLabel("X");
        plot.getAxisRenderers(XYPlot.AXIS_Y).get(0).setLabel("Y");
        plot.getAxisRenderers(XYPlot.AXIS_X).get(0).setTickSpacing(1.0);
        plot.getAxisRenderers(XYPlot.AXIS_Y).get(0).setTickSpacing(2.0);
        plot.getAxisRenderers(XYPlot.AXIS_X).get(0).setIntersection(-Double.MAX_VALUE);
        plot.getAxisRenderers(XYPlot.AXIS_Y).get(0).setIntersection(-Double.MAX_VALUE);

        // Display on screen
        getContentPane().add(new InteractivePanel(plot), BorderLayout.CENTER);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setMinimumSize(getContentPane().getMinimumSize());
        setSize(504, 327);
    }

    public static void main(String[] args) {
        Styling df = new Styling();
        df.setVisible(true);
    }
}