umontreal.iro.lecuyer.charts.XYLineChart Maven / Gradle / Ivy
Show all versions of ssj Show documentation
/*
* Class: XYLineChart
* Description:
* Environment: Java
* Software: SSJ
* Copyright (C) 2001 Pierre L'Ecuyer and Université de Montréal
* Organization: DIRO, Université de Montréal
* @author
* @since
* SSJ is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License (GPL) as published by the
* Free Software Foundation, either version 3 of the License, or
* any later version.
* SSJ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* A copy of the GNU General Public License is available at
GPL licence site.
*/
package umontreal.iro.lecuyer.charts;
import org.jfree.chart.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.renderer.xy.*;
import org.jfree.data.xy.*;
import org.jfree.data.category.*;
import org.jfree.chart.renderer.category.*;
import java.util.Locale;
import java.util.Formatter;
import java.lang.Math;
import java.awt.*;
import java.awt.geom.*;
import cern.colt.list.DoubleArrayList;
import javax.swing.JFrame;
/**
* This class provides tools to create and manage curve plots. Using the
* {@link XYLineChart} class is the simplest way to produce curve plots only.
* Each {@link XYLineChart} object is linked with a
* {@link umontreal.iro.lecuyer.charts.XYListSeriesCollection XYListSeriesCollection} data set.
*
*/
public class XYLineChart extends XYChart {
protected void init (String title, String XLabel, String YLabel) {
// create the chart...
chart = ChartFactory.createXYLineChart (
title, // chart title
XLabel, // x axis label
YLabel, // y axis label
dataset.getSeriesCollection(), // data
PlotOrientation.VERTICAL,
false, // include legend
true, // tooltips
false // urls
);
if (null != title) {
if (title.startsWith("cdf") || title.startsWith("prob") || title.startsWith("density"))
setprobFlag (true);
}
((XYPlot)chart.getPlot()).setRenderer(dataset.getRenderer());
// Initialize axis variables
initAxis();
}
protected void initAxis(){
XAxis = new Axis((NumberAxis)((XYPlot)chart.getPlot()).getDomainAxis(),
Axis.ORIENTATION_HORIZONTAL);
YAxis = new Axis((NumberAxis)((XYPlot)chart.getPlot()).getRangeAxis(),
Axis.ORIENTATION_VERTICAL);
setAutoRange(true, true);
}
/**
* Initializes a new XYLineChart instance with an empty data set.
*
*/
public XYLineChart() {
super();
dataset = new XYListSeriesCollection();
init (null, null, null);
}
/**
* Initializes a new XYLineChart instance with sets of points data.
* title is a title, XLabel is a short description of the
* x-axis, and YLabel a short description of the y-axis.
* The input parameter data represents a set of plotting data.
*
*
* For example, if one n-row matrix data1 is given as argument
* data, then the first row data1[0] represents the
* x-coordinate vector, and every other row data1
* [i], i = 1,…, n - 1, represents a y-coordinate set for a curve.
* Therefore matrix data1[i][j],
* i = 0,…, n - 1, corresponds
* to n - 1 curves, all with the same x-coordinates.
*
*
* However, one may want to plot several curves with different x-coordinates.
* In that case, one should give the curves as matrices with two rows.
* For examples, if the argument data is made of three 2-row matrices
* data1, data2 and data3, then they represents
* three different curves, data*[0] being the x-coordinates,
* and data*[1] the y-coordinates of the curves.
*
* @param title chart title.
*
* @param XLabel Label on x-axis.
*
* @param YLabel Label on y-axis.
*
* @param data series of point sets.
*
*
*/
public XYLineChart (String title, String XLabel, String YLabel,
double[][]... data) {
super();
dataset = new XYListSeriesCollection(data);
init (title, XLabel, YLabel);
}
/**
* Initializes a new XYLineChart instance with sets of points data.
* title is a title, XLabel is a short description of the
* x-axis, and YLabel a short description of the y-axis.
* If data is a n-row matrix,
* then the first row data[0] represents the
* x-coordinate vector, and every other row data
* [i], i = 1,…, n - 1, represents a y-coordinate set of points.
* Therefore matrix data[i][ ],
* i = 0,…, n - 1, corresponds
* to n - 1 curves, all with the same x-coordinates.
* However, only the first numPoints of data will
* be considered to plot each curve.
*
* @param title chart title.
*
* @param XLabel Label on x-axis.
*
* @param YLabel Label on y-axis.
*
* @param data series of point sets.
*
* @param numPoints Number of points to plot
*
*
*/
public XYLineChart (String title, String XLabel, String YLabel,
double[][] data, int numPoints) {
super();
dataset = new XYListSeriesCollection(data, numPoints);
init (title, XLabel, YLabel);
}
/**
* Initializes a new XYLineChart instance using subsets of data.
* data[x][.] will form the x-coordinates and
* data[y][.] will form the y-coordinates of the chart.
* title sets a title, XLabel is a short description of the
* x-axis, and YLabel is a short description of the y-axis.
* Warning: if the new x-axis coordinates are not monotone increasing, then
* they will automatically be sorted in increasing order so the points will
* be reordered, but the original data is not changed.
*
* @param title chart title.
*
* @param XLabel Label on x-axis.
*
* @param YLabel Label on y-axis.
*
* @param data series of point sets.
*
* @param x Index of data forming the x-coordinates
*
* @param y Index of data forming the y-coordinates
*
*
*/
public XYLineChart (String title, String XLabel, String YLabel,
double[][] data, int x, int y) {
super();
int len = data[0].length;
double[][] proj = new double[2][len];
for (int i = 0; i < len; i++) {
proj[0][i] = data[x][i];
proj[1][i] = data[y][i];
}
dataset = new XYListSeriesCollection(proj);
init (title, XLabel, YLabel);
}
/**
* Initializes a new XYLineChart instance with data data.
* The input parameter data represents a set of plotting data. A
* {@link cern.colt.list.DoubleArrayList DoubleArrayList} from the Colt library is
* used to store the data. The description is similar to the
* constructor {@link YListChart} with double[]... data.
*
* @param title chart title.
*
* @param XLabel Label on x-axis.
*
* @param YLabel Label on y-axis.
*
* @param data series of point sets.
*
*
*/
public XYLineChart (String title, String XLabel, String YLabel,
DoubleArrayList... data) {
super();
dataset = new XYListSeriesCollection(data);
init (title, XLabel, YLabel);
}
/**
* Initializes a new XYLineChart instance with data data.
* The input parameter data represents a set of plotting data.
* {@link org.jfree.data.xy.XYSeriesCollection XYSeriesCollection} is a
* JFreeChart container class to store XY plots.
*
* @param title chart title.
*
* @param XLabel Label on x-axis.
*
* @param YLabel Label on y-axis.
*
* @param data series collection.
*
*/
public XYLineChart (String title, String XLabel, String YLabel,
XYSeriesCollection data) {
super();
dataset = new XYListSeriesCollection(data);
init (title, XLabel, YLabel);
}
/**
* Adds a data series into the series collection. Vector x represents
* the x-coordinates and vector y represents the y-coordinates of
* the series. name and plotStyle are the name and the plot
* style associated to the series.
*
* @param x xi coordinates.
*
* @param y yi coordinates.
*
* @param name Name of the series.
*
* @param plotStyle Plot style of the series.
*
* @return Integer that represent the new point set's position in the JFreeChart XYSeriesCollection object.
*
*/
public int add (double[] x, double[] y, String name, String plotStyle) {
int seriesIndex = add(x,y);
getSeriesCollection().setName(seriesIndex, name);
getSeriesCollection().setPlotStyle (seriesIndex, plotStyle);
return seriesIndex;
}
/**
* Adds a data series into the series collection. Vector x represents
* the x-coordinates and vector y represents the y-coordinates of
* the series.
*
* @param x xi coordinates.
*
* @param y yi coordinates.
*
* @return Integer that represent the new point set's position in the JFreeChart XYSeriesCollection object.
*
*/
public int add (double[] x, double[] y) {
int seriesIndex = getSeriesCollection().add(x,y);
initAxis();
return seriesIndex;
}
/**
* Adds a data series into the series collection. Vector x represents
* the x-coordinates and vector y represents the y-coordinates of
* the series. Only the first numPoints of x and
* y will be taken into account for the new series.
*
* @param x xi coordinates.
*
* @param y yi coordinates.
*
* @param numPoints Number of points to add
*
* @return Integer that represent the new point set's position in the JFreeChart XYSeriesCollection object.
*
*/
public int add (double[] x, double[] y, int numPoints) {
int seriesIndex = getSeriesCollection().add(x, y, numPoints);
initAxis();
return seriesIndex;
}
/**
* Adds the new collection of data series data into the series collection.
* If data is a n-row matrix,
* then the first row data[0] represents the
* x-coordinate vector, and every other row data
* [i], i = 1,…, n - 1, represents a y-coordinate set of points.
* Therefore matrix data[i][ ],
* i = 0,…, n - 1, corresponds
* to n - 1 curves, all with the same x-coordinates.
*
* @param data series of point sets.
*
*
*/
public int add (double[][] data) {
int seriesIndex = getSeriesCollection().add(data);
initAxis();
return seriesIndex;
}
/**
* Adds the new collection of data series data into the series collection.
* If data is a n-row matrix,
* then the first row data[0] represents the
* x-coordinate vector, and every other row data
* [i], i = 1,…, n - 1, represents a y-coordinate set of points.
* Therefore matrix data[i][ ],
* i = 0,…, n - 1, corresponds
* to n - 1 curves, all with the same x-coordinates.
* However, only the first numPoints of data will
* be taken into account for the new series.
*
* @param data series of point sets.
*
* @param numPoints Number of points to plot
*
*
*/
public int add (double[][] data, int numPoints) {
int seriesIndex = getSeriesCollection().add(data, numPoints);
initAxis();
return seriesIndex;
}
/**
* Returns the chart's dataset.
*
* @return the chart's dataset.
*
*/
public XYListSeriesCollection getSeriesCollection() {
return (XYListSeriesCollection)dataset;
}
/**
* Links a new dataset to the current chart.
*
* @param dataset new dataset.
*
*
*/
public void setSeriesCollection (XYListSeriesCollection dataset) {
this.dataset = dataset;
}
/**
* Synchronizes X-axis ticks to the s-th series x-values.
*
* @param s series used to define ticks.
*
*
*/
public void setTicksSynchro (int s) {
XYSeriesCollection seriesCollection =
(XYSeriesCollection)this.dataset.getSeriesCollection();
double[] values = new double[seriesCollection.getItemCount(s)];
for(int i = 0; i < seriesCollection.getItemCount(s); i++)
values[i] = seriesCollection.getXValue(s, i);
XAxis.setLabels(values);
}
/**
* Displays chart on the screen using Swing.
* This method creates an application containing a chart panel displaying
* the chart. The created frame is positioned on-screen, and displayed before
* it is returned. The width and the height
* of the chart are measured in pixels.
*
* @param width frame width in pixels.
*
* @param height frame height in pixels.
*
* @return frame containing the chart.;
*
*/
public JFrame view (int width, int height) {
JFrame myFrame;
if(chart.getTitle() != null)
myFrame = new JFrame("XYLineChart from SSJ: " + chart.getTitle().getText());
else
myFrame = new JFrame("XYLineChart from SSJ");
ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(width, height));
myFrame.setContentPane(chartPanel);
myFrame.pack();
myFrame.setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);
myFrame.setLocationRelativeTo (null);
myFrame.setVisible(true);
return myFrame;
}
/**
* Displays bar chart on the screen using Swing.
* This method creates an application containing a bar chart panel displaying
* the chart. The created frame is positioned on-screen, and displayed before
* it is returned. The width and the height
* of the chart are measured in pixels.
*
* @param width frame width in pixels.
*
* @param height frame height in pixels.
*
* @return frame containing the bar chart.;
*
*/
public JFrame viewBar (int width, int height) {
JFrame myFrame;
if (chart.getTitle() != null)
myFrame = new JFrame("XYLineChart from SSJ: " + chart.getTitle().getText());
else
myFrame = new JFrame("XYLineChart from SSJ");
XYPlot plot = (XYPlot) chart.getPlot();
//Create the bar
plot.setDataset(0, dataset.getSeriesCollection());
final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(false, true);
renderer.setSeriesPaint(0,Color.ORANGE);
renderer.setSeriesShape(0,new Line2D.Double(0, 0, 0 , 1000));
plot.setRenderer(0, renderer);
//Create the points
plot.setDataset(1, dataset.getSeriesCollection());
final XYLineAndShapeRenderer renderer2 = new XYLineAndShapeRenderer(false, true);
renderer2.setSeriesPaint(0,Color.ORANGE);
renderer2.setSeriesShape(0,new Ellipse2D.Double(-2.0,-2.0,4.0,4.0));
plot.setRenderer(1, renderer2);
ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(width, height));
myFrame.setContentPane(chartPanel);
myFrame.pack();
myFrame.setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);
myFrame.setLocationRelativeTo (null);
myFrame.setVisible(true);
return myFrame;
}
public String toLatex (double width, double height) {
double xunit=0, yunit=0;
double[] save = new double[4];
if (dataset.getSeriesCollection().getSeriesCount() == 0)
throw new IllegalArgumentException("Empty chart");
//Calcul des parametres d'echelle et de decalage
double XScale = computeXScale(XAxis.getTwinAxisPosition());
double YScale = computeYScale(YAxis.getTwinAxisPosition());
// taille d'une unite en x et en cm dans l'objet "tikzpicture"
xunit = width / ((Math.max(XAxis.getAxis().getRange().getUpperBound(), XAxis.getTwinAxisPosition()) * XScale) - (Math.min(XAxis.getAxis().getRange().getLowerBound(), XAxis.getTwinAxisPosition()) * XScale));
// taille d'une unite en y et en cm dans l'objet "tikzpicture"
yunit = height / ((Math.max(YAxis.getAxis().getRange().getUpperBound(), YAxis.getTwinAxisPosition()) * YScale) - (Math.min(YAxis.getAxis().getRange().getLowerBound(), YAxis.getTwinAxisPosition()) * YScale));
Formatter formatter = new Formatter(Locale.US);
/*Entete du document*/
if (latexDocFlag) {
formatter.format("\\documentclass[12pt]{article}%n%n");
formatter.format("\\usepackage{tikz}%n\\usetikzlibrary{plotmarks}%n\\begin{document}%n%n");
}
if (chart.getTitle() != null)
formatter.format("%% PGF/TikZ picture from SSJ: %s%n", chart.getTitle().getText());
else
formatter.format("%% PGF/TikZ picture from SSJ %n");
formatter.format("%% XScale = %s, YScale = %s, XShift = %s, YShift = %s%n", XScale, YScale, XAxis.getTwinAxisPosition(), YAxis.getTwinAxisPosition());
formatter.format("%% Therefore, thisFileXValue = (originalSeriesXValue+XShift)*XScale%n");
formatter.format("%% and thisFileYValue = (originalSeriesYValue+YShift)*YScale%n%n");
if (chart.getTitle() != null)
formatter.format("\\begin{figure}%n");
formatter.format("\\begin{center}%n");
formatter.format("\\begin{tikzpicture}[x=%scm, y=%scm]%n", xunit, yunit);
formatter.format("\\footnotesize%n");
if (grid)
formatter.format("\\draw[color=lightgray] (%s, %s) grid[xstep = %s, ystep=%s] (%s, %s);%n",
(Math.min(XAxis.getAxis().getRange().getLowerBound(), XAxis.getTwinAxisPosition())-XAxis.getTwinAxisPosition()) * XScale,
(Math.min(YAxis.getAxis().getRange().getLowerBound(), YAxis.getTwinAxisPosition())-YAxis.getTwinAxisPosition()) * YScale,
xstepGrid*XScale, ystepGrid*YScale,
(Math.max(XAxis.getAxis().getRange().getUpperBound(), XAxis.getTwinAxisPosition())-XAxis.getTwinAxisPosition()) * XScale,
(Math.max(YAxis.getAxis().getRange().getUpperBound(), YAxis.getTwinAxisPosition())-YAxis.getTwinAxisPosition()) * YScale );
setTick0Flags();
formatter.format("%s", XAxis.toLatex(XScale) );
formatter.format("%s", YAxis.toLatex(YScale) );
formatter.format("%s", dataset.toLatex(
XScale, YScale,
XAxis.getTwinAxisPosition(), YAxis.getTwinAxisPosition(),
XAxis.getAxis().getLowerBound(), XAxis.getAxis().getUpperBound(),
YAxis.getAxis().getLowerBound(), YAxis.getAxis().getUpperBound()));
formatter.format("\\end{tikzpicture}%n");
formatter.format("\\end{center}%n");
if (chart.getTitle() != null) {
formatter.format("\\caption{");
formatter.format(chart.getTitle().getText());
formatter.format("}%n\\end{figure}%n");
}
if (latexDocFlag)
formatter.format("\\end{document}%n");
return formatter.toString();
}
}