package org.seqcode.viz.scatter;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;
import javax.imageio.ImageIO;
import org.apache.batik.dom.GenericDOMImplementation;
import org.apache.batik.svggen.SVGGraphics2D;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.annotations.XYTextAnnotation;
import org.jfree.chart.axis.LogAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.ValueMarker;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.DefaultXYDataset;
import org.jfree.ui.TextAnchor;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import Jama.Matrix;
/**
* ScatterPlot: Adapted from Multiple Dataset Demo 1 in org.jfree.chart.demo
* This class contains the chart, plot, data, and the rest of the main drawing items for a scatter plot.
*
* Extended by Shaun Mahony
*
* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-2004, by Object Refinery Limited and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* --------------------------
* SecondaryDatasetDemo1.java
* --------------------------
* (C) Copyright 2004, by Object Refinery Limited.
*
* Original Author: David Gilbert (for Object Refinery Limited).
* 30-Jan-2004 : Version 1 (DG);
*
*/
public class ScatterPlot {
protected JFreeChart chart;
protected XYPlot plot;
protected ValueAxis daxis=null;
protected ValueAxis raxis=null;
protected int width=800, height=800;
protected ScatterData data;
protected boolean batch = false;
protected boolean xLogScale = false;
protected boolean yLogScale = false;
protected String xAxisLabel="";
protected String yAxisLabel="";
protected int defaultDotSize=3;
protected Color defaultDotColor = new Color(75,75,75,50);
protected int dataLabelFontSize = 24;
protected int xAxisLabelFontSize=28;
protected int yAxisLabelFontSize=28;
protected int xAxisTickLabelFontSize=14;
protected int yAxisTickLabelFontSize=14;
/**
* Constructor: initialize the plot & chart
* @param title
*/
public ScatterPlot (String title) {
data = new ScatterData();
chart = ChartFactory.createScatterPlot(title,
"X",
"Y",
new DefaultXYDataset(), PlotOrientation.VERTICAL,
false,false,false);
chart.setBackgroundPaint(Color.white);
chart.setBorderVisible(false);
plot = chart.getXYPlot();
plot.setBackgroundPaint(Color.white);
plot.setOutlineVisible(false);
plot.setDomainGridlinesVisible(false);
plot.setRangeGridlinesVisible(false);
plot.setDomainZeroBaselineVisible(true);
plot.setRangeZeroBaselineVisible(true);
plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
this.configAxes();
}
/**
* Configure axes to log or linear scales
*/
protected void configAxes(){
if(xLogScale)
plot.setDomainAxis(new LogAxis());
else
plot.setDomainAxis(new NumberAxis());
if(yLogScale)
plot.setRangeAxis(new LogAxis());
else
plot.setRangeAxis(new NumberAxis());
daxis = this.plot.getDomainAxis();
daxis.setAxisLinePaint(Color.black);
daxis.setLabelPaint(Color.black);
daxis.setTickLabelPaint(Color.BLACK);
daxis.setTickMarkPaint(Color.BLACK);
raxis = this.plot.getRangeAxis();
raxis.setAxisLinePaint(Color.black);
raxis.setLabelPaint(Color.black);
raxis.setTickLabelPaint(Color.BLACK);
raxis.setTickMarkPaint(Color.BLACK);
if(xLogScale){
daxis.setLowerBound(1.0);
daxis.setUpperBound(1000000.0);
daxis.setAutoRange(false);
if(daxis instanceof org.jfree.chart.axis.LogAxis)
((LogAxis)daxis).setTickUnit(new NumberTickUnit(1.0));
}else{
daxis.setAutoRange(true);
}
if(yLogScale){
raxis.setLowerBound(1.0);
raxis.setUpperBound(1000000.0);
raxis.setAutoRange(false);
if(daxis instanceof org.jfree.chart.axis.LogAxis)
((LogAxis)raxis).setTickUnit(new NumberTickUnit(1.0));
}else{
raxis.setAutoRange(true);
}
daxis.setLabel(xAxisLabel);
raxis.setLabel(yAxisLabel);
daxis.setLabelFont(new Font("Tahoma", Font.BOLD, xAxisLabelFontSize));
raxis.setLabelFont(new Font("Tahoma", Font.BOLD, yAxisLabelFontSize));
daxis.setTickLabelFont(new Font("Tahoma", Font.PLAIN, xAxisTickLabelFontSize));
raxis.setTickLabelFont(new Font("Tahoma", Font.PLAIN, yAxisTickLabelFontSize));
}
/**
* Save image
* If raster is false, save a SVG, otherwise save a PNG
*
*/
public void saveImage(File f, int w, int h, boolean raster)
throws IOException {
if (raster) {
BufferedImage im =
new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = im.getGraphics();
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
chart.draw(g2, new Rectangle(0,0,w,h));
ImageIO.write(im, "png", f);
}else{
DOMImplementation domImpl =
GenericDOMImplementation.getDOMImplementation();
// Create an instance of org.w3c.dom.Document
Document document = domImpl.createDocument(null, "svg", null);
// Create an instance of the SVG Generator
SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
svgGenerator.setSVGCanvasSize(new Dimension(w,h));
// Ask the test to render into the SVG Graphics2D implementation
svgGenerator.setColor(Color.white);
svgGenerator.fillRect(0,0,w,h);
chart.draw(svgGenerator, new Rectangle(0,0,w,h));
// Finally, stream out SVG to the standard output using UTF-8
// character to byte encoding
boolean useCSS = true; // we want to use CSS style attribute
FileOutputStream outStream = new FileOutputStream(f);
Writer out = new OutputStreamWriter(outStream, "UTF-8");
svgGenerator.stream(out, useCSS);
outStream.flush();
outStream.close();
}
}
public JFreeChart getChart(){return chart;}
public int getWidth(){return width;}
public int getHeight(){return height;}
public boolean isBatch(){return batch;}
public boolean getXLogScale(){return xLogScale;}
public boolean getYLogScale(){return yLogScale;}
//Modifiers
public void setWidth(int w){width=w; }
public void setHeight(int h){height=h; }
public void setBatch(boolean b){batch=b;}
public void setGridlinesVisible(boolean v){plot.setDomainGridlinesVisible(false); plot.setRangeGridlinesVisible(false);}
public void setXLogScale(boolean l){this.xLogScale=l; this.configAxes();}
public void setYLogScale(boolean l){this.yLogScale=l; this.configAxes();}
public void setXAxisLabel(String s){this.xAxisLabel=s; daxis.setLabel(xAxisLabel);}
public void setYAxisLabel(String s){this.yAxisLabel=s; raxis.setLabel(yAxisLabel);}
public void setDataLabelFontSize(int d){dataLabelFontSize=d; chart.fireChartChanged();}
public void setXAxisLabelFontSize(int d){xAxisLabelFontSize=d; daxis.setLabelFont(new Font("Tahoma", Font.BOLD, xAxisLabelFontSize));}
public void setYAxisLabelFontSize(int d){yAxisLabelFontSize=d; raxis.setLabelFont(new Font("Tahoma", Font.BOLD, yAxisLabelFontSize));}
public void setXAxisTickLabelFontSize(int d){xAxisTickLabelFontSize=d; daxis.setLabelFont(new Font("Tahoma", Font.BOLD, xAxisTickLabelFontSize));}
public void setYAxisTickLabelFontSize(int d){yAxisTickLabelFontSize=d; raxis.setLabelFont(new Font("Tahoma", Font.BOLD, yAxisTickLabelFontSize));}
public void setXAutoRange(boolean a){daxis.setAutoRange(a);}
public void setYAutoRange(boolean a){raxis.setAutoRange(a);}
public void setXRange(double min, double max){daxis.setLowerBound(min); daxis.setUpperBound(max);}
public void setYRange(double min, double max){raxis.setLowerBound(min); raxis.setUpperBound(max);}
public void setXRangeFromData(){daxis.setLowerBound(data.getMin(0)); daxis.setUpperBound(data.getMax(0)+1);}
public void setYRangeFromData(){raxis.setLowerBound(data.getMin(1)); raxis.setUpperBound(data.getMax(1)+1);}
/**
* Add a dataset to the plot
* @param name String
* @param datasetMatrix 2D matrix
* @param c Color
* @param dotSize int
* @param drawAnnotations boolean
*/
public void addDataset(String name, Matrix datasetMatrix, Color c, int dotSize, boolean drawAnnotations, boolean drawConnectingLines, boolean drawDots){
data.loadDataset(name, datasetMatrix);
this.plot.setDataset(data.getDatasetIndex(), data.getDataset(data.getDatasetIndex()));
data.editRenderer(data.getDatasetIndex(), dotSize, c, drawConnectingLines, drawDots);
this.plot.setRenderer(data.getDatasetIndex(), data.getRenderer(data.getDatasetIndex()));
if(drawAnnotations){
List<XYTextAnnotation> annots = data.getAnnotations(data.getDatasetIndex(), 0.0, 0.0, TextAnchor.BOTTOM_RIGHT, dataLabelFontSize, Font.PLAIN, c);
for(XYTextAnnotation a : annots)
plot.addAnnotation(a);
}
}
public void addDataset(String name, Matrix datasetMatrix, Color c, int dotSize){addDataset(name, datasetMatrix, c, dotSize, false, false, true);}
public void addDataset(String name, Matrix datasetMatrix, Color c){addDataset(name, datasetMatrix, c, defaultDotSize, false, false, true);}
public void addDataset(String name, Matrix datasetMatrix){addDataset(name, datasetMatrix, defaultDotColor, defaultDotSize, false, false, true);}
/**
* Add a dataset from a file
* @param f File
* @param c Color
* @param dotSize integer
*/
public void addFileDataset(File f, Color c, int dotSize, boolean drawAnnotations){
data.loadFileDataset(f, "S"+(data.getDatasetIndex()+1), 1);
this.plot.setDataset(
data.getDatasetIndex(), data.getDataset(data.getDatasetIndex())
);
data.editRenderer(data.getDatasetIndex(), dotSize, c);
this.plot.setRenderer(data.getDatasetIndex(), data.getRenderer(data.getDatasetIndex()));
if(drawAnnotations){
List<XYTextAnnotation> annots = data.getAnnotations(data.getDatasetIndex(), 0.0, 0.0, TextAnchor.BOTTOM_RIGHT, dataLabelFontSize, Font.PLAIN, c);
for(XYTextAnnotation a : annots)
plot.addAnnotation(a);
}
configAxes();
}
/**
* Add a random dataset (for testing)
*/
public void addRandomDataset(Color c, int dotSize){
data.loadRandomDataset("Random"+(data.getDatasetIndex()+1));
this.plot.setDataset(
data.getDatasetIndex(), data.getDataset(data.getDatasetIndex())
);
data.editRenderer(data.getDatasetIndex(), dotSize, c);
this.plot.setRenderer(data.getDatasetIndex(), data.getRenderer(data.getDatasetIndex()));
configAxes();
}
/**
* Add a domain marker to the plot
*/
public void addDomainMarker(double position){
ValueMarker marker = new ValueMarker(position); // position is the value on the axis
marker.setPaint(Color.red);
plot.addDomainMarker(marker);
}
/**
* Add a range marker to the plot
*/
public void addRangeMarker(double position){
ValueMarker marker = new ValueMarker(position); // position is the value on the axis
marker.setPaint(Color.red);
plot.addRangeMarker(marker);
}
/**
* Remove the last dataset on the pile
*/
public void removeLastDataset(){
if (data.getDatasetIndex() >= 0) {
plot.setDataset(data.getDatasetIndex(), null);
plot.setRenderer(data.getDatasetIndex(), null);
data.removeLastDataset();
}
}
}