package evoker;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.data.xy.XYDataset;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.text.NumberFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.FieldPosition;
import java.util.Locale;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
public class PlotPanel extends JPanel {
/**
* Mode, determining the way, the Diagram responses to mouse gestures.
* <code>true</code> means lasso select, <code>false</code> means zooming
* in.
*/
ChartPanel generatePlot;
protected Genoplot theGenoplot;
private JFreeChart jfc;
private PlotData data;
private String title, xlab, ylab;
private boolean foundData;
static NumberFormat nf = NumberFormat.getInstance(Locale.US);
boolean longStats;
double totalMaf;
int totalSamples;
JPanel statistics = null;
static {
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
}
PlotPanel(Genoplot gp, String title, PlotData pd, int plotHeight, int plotWidth,
boolean longStats, double totalMaf,
int totalSamples) {
this.theGenoplot = gp;
this.title = title;
this.data = pd;
this.longStats = longStats;
this.totalMaf = totalMaf;
this.totalSamples = totalSamples;
if (pd.getCoordSystem().matches("POLAR")) {
this.xlab = String.valueOf("\u03F4");
this.ylab = String.valueOf("r");
} else {
this.xlab = String.valueOf("X");
this.ylab = String.valueOf("Y");
}
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
this.setPreferredSize(new Dimension(plotHeight, plotWidth));
this.setMaximumSize(new Dimension(plotHeight, plotWidth));
}
protected void refresh() {
this.removeAll();
XYSeriesCollection xysc = data.generatePoints();
if (xysc != null) {
setFoundData(true);
generatePlot = generatePlot(xysc);
add(generatePlot);
statistics = new JPanel();
add(generateInfo());
} else {
setFoundData(false);
this.setBackground(Color.WHITE);
add(Box.createVerticalGlue());
JLabel l = new JLabel("No data found for " + title);
l.setAlignmentX(Component.CENTER_ALIGNMENT);
add(l);
add(Box.createVerticalGlue());
}
}
private void setFoundData(boolean b) {
foundData = b;
}
void saveToFile(File f) throws IOException {
ChartUtilities.saveChartAsPNG(f, jfc, 400, 400);
}
public JPanel generateInfo() {
statistics.setBackground(Color.white);
boolean compressStats = true;
JLabel mafLabel = new JLabel();
JLabel gpcLabel = new JLabel();
JLabel hwpLabel = new JLabel();
double maf = data.getMaf();
double mafAvg = totalMaf / totalSamples;
double mafScore = (maf - mafAvg) * Math.sqrt(2 * data.getSampleNum()) / Math.sqrt(mafAvg * (1 - mafAvg));
if (longStats) {
if (mafScore > 3) {
mafLabel.setText("<html><b><u>MAF: " + nf.format(data.getMaf())
+ "</u></b></html>");
} else {
mafLabel.setText("MAF: " + nf.format(data.getMaf()));
}
if (1 - data.getGenopc() > 0.02) {
gpcLabel.setText("<html><b><u>GPC: " + nf.format(data.getGenopc())
+ "</u></b></html>");
} else {
gpcLabel.setText("GPC: " + nf.format(data.getGenopc()));
}
if (data.getHwpval() < 10e-5) {
hwpLabel.setText("<html><b><u>HWE pval: "
+ formatPValue(data.getHwpval()) + "</u></b></html>");
} else {
hwpLabel.setText("HWE pval: " + formatPValue(data.getHwpval()));
}
} else {
if (mafScore > 3) {
mafLabel.setText("<html><b><u>" + nf.format(data.getMaf())
+ "</u></b>/</html>");
} else {
mafLabel.setText(nf.format(data.getMaf()) + "/");
}
if (1 - data.getGenopc() > 0.02) {
gpcLabel.setText("<html><b><u>" + nf.format(data.getGenopc())
+ "</u></b>/</html>");
} else {
gpcLabel.setText(nf.format(data.getGenopc()) + "/");
}
if (data.getHwpval() < 10e-5) {
hwpLabel.setText("<html><b><u>" + formatPValue(data.getHwpval())
+ "</u></b></html>");
} else {
hwpLabel.setText(formatPValue(data.getHwpval()));
}
}
statistics.add(mafLabel);
statistics.add(gpcLabel);
statistics.add(hwpLabel);
return statistics;
}
public void updateInfo() {
statistics.removeAll();
generateInfo();
statistics.revalidate();
}
public String generateInfoStr() {
return "MAF: " + nf.format(data.getMaf()) + "\tGPC: "
+ nf.format(data.getGenopc()) + "\tHWE pval: "
+ formatPValue(data.getHwpval());
}
private ChartPanel generatePlot(XYSeriesCollection xysc) {
jfc = ChartFactory.createScatterPlot(title, xlab, ylab, xysc,
PlotOrientation.VERTICAL, false, false, false);
jfc.addSubtitle(new TextTitle("(n=" + data.getSampleNum() + ")"));
XYPlot thePlot = jfc.getXYPlot();
thePlot.setBackgroundPaint(Color.white);
thePlot.setOutlineVisible(false);
XYItemRenderer xyd = thePlot.getRenderer();
Shape dot = new Ellipse2D.Double(-1.5, -1.5, 3, 3);
xyd.setSeriesShape(0, dot);
xyd.setSeriesShape(1, dot);
xyd.setSeriesShape(2, dot);
xyd.setSeriesShape(3, dot);
xyd.setSeriesPaint(0, Color.BLUE);
xyd.setSeriesPaint(1, new Color(180, 180, 180));
xyd.setSeriesPaint(2, Color.GREEN);
xyd.setSeriesPaint(3, Color.RED);
xyd.setBaseToolTipGenerator(new ZitPlotToolTipGenerator());
EvokerChartPanel cp = new EvokerChartPanel(jfc, data, this);
cp.setDisplayToolTips(true);
cp.setDismissDelay(10000);
cp.setInitialDelay(0);
cp.setReshowDelay(0);
return cp;
}
public double getMaxDim() {
double range = data.getMaxDim() - data.getMinDim();
return data.getMaxDim() + 0.05 * range;
}
public double getMinDim() {
double range = data.getMaxDim() - data.getMinDim();
return data.getMinDim() - 0.05 * range;
}
public void setDimensions(double min, double max) {
if (jfc != null) {
jfc.getXYPlot().setRangeAxis(new LinkedAxis(ylab, min, max));
jfc.getXYPlot().getRangeAxis().setRange(min, max);
if (data.getCoordSystem().matches("POLAR")) {
jfc.getXYPlot().setDomainAxis(new LinkedAxis(xlab, 0, 2));
jfc.getXYPlot().getDomainAxis().setRange(0, 2);
} else {
jfc.getXYPlot().setDomainAxis(new LinkedAxis(xlab, min, max));
jfc.getXYPlot().getDomainAxis().setRange(min, max);
}
}
}
public static String formatPValue(double pval) {
DecimalFormat df;
// java truly sucks for simply restricting the number of sigfigs but
// still
// using scientific notation when appropriate
if (pval < 0.001) {
df = new DecimalFormat("0.0E0", new DecimalFormatSymbols(Locale.US));
} else {
df = new DecimalFormat("0.000", new DecimalFormatSymbols(Locale.US));
}
return df.format(pval, new StringBuffer(),
new FieldPosition(NumberFormat.INTEGER_FIELD)).toString();
}
class ZitPlotToolTipGenerator extends StandardXYToolTipGenerator {
public double round3(double n) {
double result = n * 100000;
result = Math.round(result);
result = result / 100000;
return result;
}
public ZitPlotToolTipGenerator() {
super();
}
public String generateToolTip(XYDataset dataset, int series, int item) {
return data.getIndInClass(series, item) + " ("
+ round3(dataset.getXValue(series, item)) + ", "
+ round3(dataset.getYValue(series, item)) + ")";
// + dataset.getXValue(series, item) + ", "
// + dataset.getYValue(series, item) + ")";
}
}
public JFreeChart getChart() {
return jfc;
}
public PlotData getPlotData() {
return data;
}
public boolean hasData() {
return foundData;
}
}