DMelt:Plots/3 Custom Plots

From HandWiki
Member



Custom plots in 2D

You can create fully custom plots with arbitrary layouts by writing Jython and Java code and accessing internal methods. First, let us consider a simple plots based on the class jhplot.HPlotXY jhplot.HPlotXY. Using the method "getPlot()" of this class one can return a plot object of the Plot Plot class that can be changed using an arbitrary layout. Let us consider a simple example:


from java.awt import Color,Font
from java.util import Random
from jhplot import * 

c1 =HPlotXY("Functions",600,400)
c1.visible()
c1.setGTitle("Functions")
c1.setNameX("X")
c1.setNameY("Values")

p1=F1D('x*x', -10,10)
p1.setLineStyle(1)

p2=F1D('x*x*cos(x)', -10,10)
p2.setLineStyle(2)
p2.setColor(Color.red)

c1.setRangeY(0,3)
c1.setRangeX(-1.2,1.2)

c1.draw(p1)
c1.draw(p2)

# c1.export("test.svg");

The output plots is:

DMelt example: HPlotXY canvas for analytic functions

You can see that jhplot.HPlotXY jhplot.HPlotXY is very similar to jhplot.HPlot jhplot.HPlot. However, it has several features that can help to build non-standard layouts.


In order to access all such plotting zones, you can look at the following methods:

c1=HPlotXY("Cosmology",600,700,0)
c1.visible()
ef=c1.getFactory()
plot=c1.getPlot()
env=c1.Env()

The function "getFactory()" returns class, while getPlot() returns the actual plotting area. Look at the API of these classes:

The ElementFactory ElementFactory class cab be used to create axis, titles, legends and subplots. In order to export plots to one of the vector-graphics formats supported by dmelt, use the usual method:

c1.export("image.svg")

(change the extension to use different file format).


Now let us build an example that shows a plot with two subplots, custom title and data points with the legends.

from java.awt import *;
from org.jplot2d.element import *
from org.jplot2d.layout import *
from org.jplot2d.sizing import *
from org.jplot2d.transform import *
from org.jplot2d.util import *
from org.jplot2d.util import *
from jhplot import *
from array import *



c1=HPlotXY("Cosmology",600,700,0)
c1.visible()
ef=c1.getFactory()
p=c1.getPlot()


title=ef.createTitle("Complex plot")
title.setFontScale(2);
p.addTitle(title);


# subplots
usp = ef.createSubplot()
lsp = ef.createSubplot()
usp.setPreferredContentSize(380, 260)
lsp.setPreferredContentSize(380, 160);
lsp.getMargin().setExtraTop(10);
p.setLayoutDirector(GridLayoutDirector());
p.addSubplot(usp,  GridConstraint(0, 1));
p.addSubplot(lsp, GridConstraint(0, 0));

#upper subplot Axes
uspx = ef.createAxes(2)
uspx[0].getTitle().setText("wavelength $\\mathrm{\\lambda}$ [$\\mathrm{\\micro}$m]");
uspx[0].getTitle().setFontSize(10);
uspx[0].getTickManager().setRange(Range.Double(10, 2e6));
uspx[0].getTickManager().getAxisTransform().setTransform(TransformType.LOGARITHMIC);
uspx[1].setLabelVisible(False);


uspy = ef.createAxes(2);
uspy[0].getTitle().setText("flux density [Jy]");
uspy[0].getTitle().setFontSize(12);
uspy[0].getTickManager().setRange(Range.Double(0.05, 1200));
uspy[0].getTickManager().getAxisTransform().setTransform(TransformType.LOGARITHMIC);
uspy[0].getTickManager().setLabelFormat("%.0f");
uspy[1].setLabelVisible(False);
usp.addXAxes(uspx);
usp.addYAxes(uspy);

# lower subplot Axes
lspx = ef.createAxes(2)
lspx[0].getTitle().setText("wavelength $\\mathrm{\\lambda}$ [$\\mathrm{\\micro}$m]");
lspx[0].getTitle().setFontSize(10);
lspx[0].getTickManager().setRange(Range.Double(10, 1500));
lspx[0].getTickManager().getAxisTransform().setTransform(TransformType.LOGARITHMIC);
lspx[1].setLabelVisible(False);

lspy = ef.createAxes(2);
lspy[0].getTitle().setText("residual [Jy]");
lspy[0].getTitle().setFontSize(10);
lspy[0].getTickManager().setRange(Range.Double(-0.7, 0.7));
lspy[0].getTickManager().setTicks(3);
lspy[1].setLabelVisible(False);
lsp.addXAxes(lspx);
lsp.addYAxes(lspy);

#Layer
ulayer = ef.createLayer();
usp.addLayer(ulayer, uspx[0], uspy[0]);
llayer = ef.createLayer();
lsp.addLayer(llayer, lspx[0], lspy[0]);

#solid line
solx = array('d', [10, 2000000])
soly = array('d', [0.09, 900])
sol = ef.createXYGraph(solx, soly);
sol.setColor(Color.BLUE);
sol.getLegendItem().setVisible(False);
ulayer.addGraph(sol)

#dashed line
dlx= array('d',[10, 2000000] )
dly = array('d', [0.1, 820])
dl = ef.createXYGraph(dlx, dly);
dl.setColor(Color.BLUE);
dl.setLineStroke(ef.createStroke(1, [1, 3 ]));
dl.getLegendItem().setVisible(False);
ulayer.addGraph(dl);


#ISO
xx= array('d',[15] )
xy = array('d',[ 0.1059 ]);
xye = array('d',[ 0.0212 ]);
xl = ef.createXYGraph(xx, xy, None, None, xye, xye, "Xilouris et al. 2004");
xl.setColor(Color.GREEN);
xl.setLineVisible(False);
xl.setSymbolVisible(True);
xl.setSymbolShape(SymbolShape.SQUARE);
ulayer.addGraph(xl);


# IRAS
gx = array('d',[ 24.9, 59.9, 99.8 ])
gy = array('d',[0.187, 0.546, 0.559])
gye = array('d',[ 0.0281, 0.0819, 0.0839])
gl = ef.createXYGraph(gx, gy, None, None, gye, gye, "Golombek et al. 1988");
gl.setColor(Color.GREEN);
gl.setLineVisible(False);
gl.setSymbolVisible(True);
gl.setSymbolShape(SymbolShape.FTRIANGLE);
ulayer.addGraph(gl);


# legend
usp.getLegend().setPosition(None);
usp.getLegend().setColumns(1);
usp.getLegend().setLocation(-10, 250);
usp.getLegend().setHAlign(HAlign.LEFT);
usp.getLegend().setVAlign(VAlign.TOP);
usp.getLegend().setBorderVisible(False);
usp.getLegend().setFontSize(12);


slrx =array('d',[ 10, 1000 ]);
slry = array('d',[ 0, 0 ]);
slrl = ef.createXYGraph(slrx, slry);
slrl.setColor(Color.BLUE);
slrl.getLegendItem().setVisible(False);
llayer.addGraph(slrl);


xry = array('d',[-0.01 ]);
xrl = ef.createXYGraph(xx, xry, None, None, xye, xye);
xrl.setColor(Color.GREEN);
xrl.setLineVisible(False);
xrl.setSymbolVisible(True);
xrl.setSymbolShape(SymbolShape.SQUARE);
xrl.getLegendItem().setVisible(False);
llayer.addGraph(xrl);

tx = array('d',[100, 160, 250, 350, 500])
tye = array('d',[0.129, 0.168, 0.215, 0.267, 0.375])
ty = array('d',[0.517, 0.673, 0.86, 1.074, 1.426]);
tl = ef.createXYGraph(tx, ty, None, None, tye, tye, "This paper");
tl.setColor(Color.RED);
tl.setLineVisible(False);
tl.setSymbolVisible(True);
tl.setSymbolShape(SymbolShape.FOCTAGON);
ulayer.addGraph(tl)



trry = array('d',[0.01, -0.03, -0.13, -0.21, -0.26]);
tx = array('d',[100, 160, 250, 350, 500])
tye = array('d',[0.129, 0.168, 0.215, 0.267, 0.375])
trl = ef.createXYGraph(tx, trry, None, None, tye, tye);
trl.setColor(Color.RED);
trl.setLineVisible(False);
trl.setSymbolVisible(True);
trl.setSymbolShape(SymbolShape.FOCTAGON);
trl.getLegendItem().setVisible(False);
llayer.addGraph(trl);

The original package used to make this code is called "jplot2d" and the description of the most essential methods is give here jplot2d wiki.

The output image created by the above code is:

DMelt example: Example of jplot2d usage. Complex layout, subplots, log scale


Building titles

After you create the "plot" object of the class org.jplot2d.element.Plot org.jplot2d.element.Plot and "ef" factory object using org.jplot2d.element.ElementFactory org.jplot2d.element.ElementFactory class, you can add a title as:

from org.jplot2d.element import *
title = ef.createTitle("Custom Title")
title.setFontScale(2)
plot.addTitle(title)

The "title" object belongs to org.jplot2d.element.Title org.jplot2d.element.Title class.

You can use TeX-like formatting of strings in plots. Entering math mode using a "dollar" symbol it is possible to insert Greek characters, for instance using

\\alpha - greek alpha 
\\beta  - greek beta
{| class="wikitable sortable" border=1
!  # superscript symbol 
|-
|}
_  # subscript symbol

Here is how to show math:

text="$A_{1.3}^{b-3/2}$"
text="$\\alpha_{1.3}^{\\beta-3/2}$"

The following special symbols are available:

  • All the lower-case Greek letters.
  • The following upper-case Greek letters: \Gamma, \Delta, \Theta, \Lambda, \Xi, \Pi, \Sigma, \Upsilon, \Phi, \Psi, \Omega .
  • The \angstrom and \micro symbols.

To insert other symbols you can use the Unicode escape sequence \uxxxx , where xxxx is the hexadecimal code of the symbol. For example, \u2299 corresponds to the circle dot operator, which can also be used as symbol for the Sun. Use [1] table to look at how to map unicode characters.

Creating Axes

To create axised for X and Y, use "createAxis" method of "ef" factory object of org.jplot2d.element.ElementFactory org.jplot2d.element.ElementFactory class

xaxis = ef.createAxis();
yaxis = ef.createAxis();
# setting an axis transform to LOGARITHMIC
xaxis.getTickManager().getAxisTransform().setTransform(TransformType.LOGARITHMIC);

The objects "xaxis" and "yaxis" belong to Axis Axis class. To add an axis to the plot, use these methds:

plot.addXAxis(xaxis)
plot.addYAxis(yaxis)

You may want 2 x-axes and 2 y-axes to box the plot contents. In this case, 2 x-axes or y-axes can be created and added together. The created 2 x-axes share the same tickManager. And so the 2 y-axes.

xaxes = ef.createAxes(2)
yaxes = ef.createAxes(2)
# setting an axis transform to LOGARITHMIC
xaxes[0].getTickManager().getAxisTransform().setTransform(TransformType.LOGARITHMIC);
plot.addXAxes(xaxes) # add them to the plot
plot.addYAxes(yaxes)


Let us show how to make titles, subtitles and axes in this example:

from org.jplot2d.element import *
from org.jplot2d.util  import *
from jhplot import *
from array import *
from java.awt import *

c1=HPlotXY(False)
c1.visible()
ef=c1.getFactory()
plot=c1.getPlot()
title=ef.createTitle("Custom Title")
title.setFontScale(2)
plot.addTitle(title)

subtitle = ef.createTitle("Custom Subtitle")
subtitle.setFontScale(1.2)
plot.addTitle(subtitle)
copyRight = ef.createTitle('\u00A9 2012 jplot2d project (LGPL)'.decode('unicode-escape'))
copyRight.setFontScale(1)
copyRight.setColor(Color.BLUE.darker());
copyRight.setPosition(TitlePosition.BOTTOMRIGHT);
plot.addTitle(copyRight);

xaxis = ef.createAxis();
yaxis = ef.createAxis();
xaxis.getTitle().setText("x axis");
plot.addXAxis(xaxis);
yaxis.getTitle().setText("y axis");
plot.addYAxis(yaxis);


The resulting plot is:

DMelt example: Example of JPlot2D usage (II) with custom titles.

Creating layers

A layer can associate with a x-axis and a y-axis, i.e. it is associated with a x AxisTransform and a y AxisTrasform. When adding a layer to a plot, the associated x AxisTransform and y AxisTrasform must be given as arguments, and they must already exist in the plot (by adding the x axis and y axis object).

layer = ef.createLayer();
# The xaxis and yaxis must has been added to the plot
plot.addLayer(layer, xaxis.getTickManager().getAxisTransform(), yaxis.getTickManager().getAxisTransform())

The "layer" object belongs to the org.jplot2d.element.Layer org.jplot2d.element.Layer class. You can extract layers from the plots as:

layers = plot.getLayers()

Creating Graphs

A 2d graph can be created with 2 double array

from array import *
x = array('d',[0,1,2,3])
y = array('d',[0,2,1,4])
graph = ef.createXYGraph(x, y)
layer.addGraph(graph)  # add this graph to layer

Similarly, your code in Java will look as:

double[] x = new double[] {0,1,2,3};
double[] y = new double[] {0,2,1,4};
XYGraph graph = ef.createXYGraph(x, y);
layer.addGraph(graph)  # add this graph to layer

The "layer" object belongs to the org.jplot2d.element.XYGraph org.jplot2d.element.XYGraph class. You can customize the graph using the methods:

graph.setColor(Color.GREEN);
graph.setLineVisible(False);
graph.setSymbolVisible(True);
graph.setSymbolShape(SymbolShape.SQUARE);

Look at the org.jplot2d.element.XYGraph org.jplot2d.element.XYGraph class.


See the org.jplot2d.util.SymbolShape org.jplot2d.util.SymbolShape class.

Data points can have errors bars in X and Y. Create a XYGraph with the given x/y array, x low/high error array and y low/high error array, use this method:

graph=ef.createXYGraph(x_array, y_array, xErrorLow, xErrorHigh, yErrorLow, yErrorHigh, name)

Creating Annotations

There are several kind of annotations can be created

  1. symbol annotation A point annotation with a symbol and a text string
  2. horizontal line annotation A horizontal line annotation to highlight a value.
  3. vertical line annotation A vertical line annotation to highlight a value.
  4. horizontal strip annotation A horizontal strip annotation to highlight a range.
  5. vertical strip annotation A vertical strip annotation to highlight a range.
  6. rectangle annotation A rectangle annotation to highlight a area.

The "annotations" objects belong to the org.jplot2d.element.Annotation org.jplot2d.element.Annotation class. Look at how the annotations can be made:

ann0 = ef.createSymbolAnnotation(x, y, "text annotation") # symbol annotation
ann1 = ef.createHLineAnnotation(y)       #  horizontal line annotation
ann2 = ef.createHStripAnnotation(y1, y2) #  horizontal strip annotation
layer.addAnnotation(annotation) # Adding an annotation to a layer