Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 5th, 2012  |  syntax: None  |  size: 13.79 KB  |  hits: 11  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*
  2.  *
  3.  */
  4. package framework.visualization;
  5.  
  6. import java.awt.Color;
  7. import java.awt.Component;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10.  
  11. import javax.swing.table.DefaultTableModel;
  12. import javax.swing.table.TableCellRenderer;
  13. import javax.swing.table.TableModel;
  14.  
  15. import org.jdesktop.swingx.JXTable;
  16. import org.jfree.chart.axis.CategoryAxis;
  17. import org.jfree.chart.axis.NumberAxis;
  18. import org.jfree.chart.labels.BoxAndWhiskerToolTipGenerator;
  19. import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
  20. import org.jfree.chart.plot.CategoryPlot;
  21. import org.jfree.chart.plot.PlotOrientation;
  22. import org.jfree.chart.plot.XYPlot;
  23. import org.jfree.chart.renderer.category.BarRenderer;
  24. import org.jfree.chart.renderer.category.BoxAndWhiskerRenderer;
  25. import org.jfree.chart.renderer.xy.XYDotRenderer;
  26. import org.jfree.data.category.DefaultCategoryDataset;
  27. import org.jfree.data.statistics.BoxAndWhiskerCalculator;
  28. import org.jfree.data.statistics.BoxAndWhiskerItem;
  29. import org.jfree.data.statistics.DefaultBoxAndWhiskerCategoryDataset;
  30. import org.jfree.data.xy.XYSeries;
  31. import org.jfree.data.xy.XYSeriesCollection;
  32.  
  33. import framework.data.Current;
  34. import framework.data.Result;
  35. import framework.data.Tuple;
  36.  
  37. // TODO: Change labeling of distance between two points or let it out.
  38.  
  39. /**
  40.  * A factory for creating plots.
  41.  *
  42.  * @author Rene Glebke, Matthias Hannen
  43.  */
  44. public abstract class PlotterFactory {
  45.  
  46.         /**
  47.          * Creates a new XYPlot for drawing one result attribute combination.
  48.          *
  49.          * @param title The title of the plot.
  50.          * @param data The data to be plotted.
  51.          *
  52.          * @return The XYPlot that can be attached to a JFreeChart instance.
  53.          */
  54.         public static PlotContainer createXYPlot(final String title, final List<PlotData> data) {
  55.                 // Create a new "XYSeries" used to store normal "points"
  56.                 XYSeries series = new XYSeries("Data");
  57.                 // Create another series that will store points marked as outliers
  58.                 XYSeries seriesOutlier = new XYSeries("Outliers");
  59.  
  60.                 // Create a table model so we can show the selected columns within the plot window
  61.                 DefaultTableModel dataTableModel = new DefaultTableModel(new String[] { "Result" }, 0);
  62.                 JXTable dataTable = new JXTable(dataTableModel)
  63.                 {
  64.                         // Overwriting the default renderer to get coloring of specific rows
  65.                         public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
  66.  
  67.                                 Component c = super.prepareRenderer(renderer, row, column);
  68.                                 int convertedRow = this.convertRowIndexToModel(row);
  69.                                 TableModel dataTableModel = this.dataModel;
  70.                                 int column1 = dataTableModel.getColumnCount() - 1;
  71.  
  72.                                 // Coloring the row light red, if the result marks an outlier
  73.                                 if ((Double)dataTableModel.getValueAt(convertedRow, column1) != 0) {
  74.                                         c.setBackground(new Color (255, 200, 200));
  75.                                 }
  76.  
  77.                                 // Set the backgroundcolor for selected rows
  78.                                 if (isRowSelected(row)) {
  79.                                         c.setBackground(new Color(150,150,255));
  80.                                 }
  81.  
  82.                                 return c;
  83.                         }
  84.                 };
  85.  
  86.                 // Create three XYSeries collections so we can render them independently
  87.                 XYSeriesCollection dataset = new XYSeriesCollection();  // Normal series
  88.  
  89.                 // Set up renderers that paint our three different series in different styles
  90.                 XYDotRenderer dotRender = new XYDotRenderer();                                  // Normal series
  91.  
  92.                 // The plot
  93.                 PlotContainer plotContainer = new PlotContainer();
  94.  
  95.                 // Get the selected result and iterate through all rows of the dataset ...
  96.                 List<Double> result = data.get(0).getData();
  97.                 List<Double> data1 = data.get(1).getData();
  98.                 List<Double> data2 = data.get(2).getData();
  99.  
  100.                 for (int i = 0; i < result.size(); i++) {
  101.                         if (result.get(i) == 0) {
  102.                                 series.add(data1.get(i), data2.get(i));
  103.                         }
  104.                         else {
  105.                                 seriesOutlier.add(data1.get(i), data2.get(i));
  106.                         }
  107.                         dataTableModel.addRow(new Double[] { result.get(i) });
  108.                 }
  109.  
  110.  
  111.                 dataset.addSeries(series);
  112.                 dataset.addSeries(seriesOutlier);
  113.  
  114.                 // Normal dots, 4x4 px in size, different colors for (non)outliers
  115.                 dotRender.setDotHeight(4);
  116.                 dotRender.setDotWidth(4);
  117.                 dotRender.setSeriesPaint(0, Color.black);
  118.                 dotRender.setSeriesPaint(1, Color.red);
  119.  
  120.                 // Finally, create the XYPlot object with default axes and attached data
  121.                 XYPlot plot = new XYPlot(dataset, new NumberAxis(), new NumberAxis(), dotRender);
  122.  
  123.  
  124.                 plotContainer.setPlot(plot);
  125.  
  126.                 plotContainer.setDataTable(dataTable);
  127.                 plotContainer.setData(data);
  128.  
  129.                 plotContainer.distanceMarking = true;
  130.                 plotContainer.pointHighlighting = true;
  131.  
  132.                 // Finally, return the plot
  133.                 return plotContainer;
  134.         }
  135.  
  136.         /**
  137.          * Creates a new XYPlot for drawing a combined XY plot from two results. The attributes are the same for both results.
  138.          *
  139.          * @param title The title of the plot.
  140.          * @param data The data to be plotted.
  141.          *
  142.          * @return XYPlot to be used in the creation of a JFreeChart object to display the data.
  143.          */
  144.         public static PlotContainer createCombinedXYPlot(final String title, final List<PlotData> data) {
  145.  
  146.                 // Create a new "XYSeries" used to store normal "points"
  147.                 XYSeries series = new XYSeries("Data");
  148.                 // Create three series that will store points marked as outliers
  149.                 XYSeries seriesOutlier1 = new XYSeries("Outliers of algo 1");
  150.                 XYSeries seriesOutlier2 = new XYSeries("Outliers of algo 2");
  151.                 XYSeries seriesOutlier3 = new XYSeries("Outliers of both algos");
  152.  
  153.                 // Create a table model so we can show the selected columns within the plot window
  154.                 DefaultTableModel dataTableModel = new DefaultTableModel(new String[] { "Result 1", "Result 2" }, 0);
  155.                 JXTable dataTable = new JXTable(dataTableModel)
  156.                 {
  157.                         // Overwriting the default renderer to get coloring of specific rows
  158.                         public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
  159.  
  160.                                 Component c = super.prepareRenderer(renderer, row, column);
  161.                                 int convertedRow = this.convertRowIndexToModel(row);
  162.                                 TableModel dataTableModel = this.dataModel;
  163.                                 int column1 = dataTableModel.getColumnCount() - 2;
  164.                                 int column2 = dataTableModel.getColumnCount() - 1;
  165.  
  166.                                 // Coloring the row light red, if the result marks an outlier
  167.                                 if ((Double)dataTableModel.getValueAt(convertedRow, column1) != 0) {
  168.                                         c.setBackground(new Color (255, 200, 200));
  169.                                 }
  170.  
  171.                                 if ((Double)dataTableModel.getValueAt(convertedRow, column2) !=0) {
  172.                                         c.setBackground(new Color(255,230,102));
  173.                                 }
  174.                                 // Coloring the row green, if both results mark an outlier
  175.                                 if ((Double)dataTableModel.getValueAt(convertedRow, column1) != 0 && (Double)dataTableModel.getValueAt(convertedRow, column2) != 0) {
  176.                                         c.setBackground(new Color(204,255,204));
  177.                                 }
  178.  
  179.                                 // Set the backgroundcolor for selected rows
  180.                                 if (isRowSelected(row)) {
  181.                                         c.setBackground(new Color(150,150,255));
  182.                                 }
  183.  
  184.                                 return c;
  185.                         }
  186.                 };
  187.  
  188.                 // Get the selected results and iterate through all rows of the dataset ...
  189.                 List<Double> result = data.get(0).getData();
  190.                 List<Double> result2 = data.get(1).getData();
  191.                 List<Double> data1 = data.get(2).getData();
  192.                 List<Double> data2 = data.get(3).getData();
  193.  
  194.                 //Create three XYSeries collections so we can render them independently
  195.                 XYSeriesCollection dataset = new XYSeriesCollection();  // Normal series
  196.  
  197.                 // Set up renderers that paint our three different series in different styles
  198.                 XYDotRenderer dotRender = new XYDotRenderer();                                  // Normal series
  199.  
  200.                 // The plot
  201.                 PlotContainer plotContainer = new PlotContainer();
  202.  
  203.                 // We will iterate through result1 using the for construction and through result2 using an iterator
  204.                 for (int i = 0; i < result.size(); i++) {
  205.                         // If algorithm 1 has marked this point as an outlier...
  206.                         if(result.get(i) != 0) {
  207.                                 // ... and if algorithm 2 has also marked it as an outlier...
  208.                                 if(result2.get(i) != 0) {
  209.                                         // ... then add it to the third series
  210.                                         seriesOutlier3.add(data1.get(i), data2.get(i));
  211.                                 }
  212.                                 // ... else add it to the outlier series of algorithm 1
  213.                                 else {
  214.                                         seriesOutlier1.add(data1.get(i), data2.get(i));
  215.                                 }
  216.                         }
  217.                         // ... or if algorithm 2 has marked this point as an outlier (and algorithm 1 hasn't)...
  218.                         else if(result2.get(i) != 0) {
  219.                                 // ... then add it to the second series
  220.                                 seriesOutlier2.add(data1.get(i), data2.get(i));
  221.                         }
  222.                         // ... else add it to the "normal" series
  223.                         else {
  224.                                 series.add(data1.get(i), data2.get(i));
  225.                         }
  226.  
  227.                         // And also add the point to the table model
  228.                         dataTableModel.addRow(new Double[] { result.get(i), result2.get(i) });
  229.                 }
  230.  
  231.                 dataset.addSeries(series);
  232.                 dataset.addSeries(seriesOutlier1);
  233.                 dataset.addSeries(seriesOutlier2);
  234.                 dataset.addSeries(seriesOutlier3);
  235.  
  236.                 // Normal dots, 4x4 px in size, different colors for (non)outliers of different algos
  237.                 dotRender.setDotHeight(4);
  238.                 dotRender.setDotWidth(4);
  239.                 dotRender.setSeriesPaint(0, Color.black);
  240.                 dotRender.setSeriesPaint(1, Color.red);
  241.                 dotRender.setSeriesPaint(2, Color.orange);
  242.                 dotRender.setSeriesPaint(3, new Color (0, 200, 0));
  243.  
  244.                 // Finally, create the XYPlot object with default axes and attached data
  245.                 XYPlot plot = new XYPlot(dataset, new NumberAxis(), new NumberAxis(), dotRender);
  246.  
  247.                 plotContainer.setPlot(plot);
  248.                 plotContainer.setDataTable(dataTable);
  249.                 plotContainer.setData(data);
  250.  
  251.                 plotContainer.distanceMarking = true;
  252.                 plotContainer.pointHighlighting = true;
  253.  
  254.                 // Finally, return the plot
  255.                 return plotContainer;
  256.         }
  257.  
  258.         /**
  259.          * Creates a new CategoryPlot for drawing a box plot.
  260.          *
  261.          * @param title The title of the plot.
  262.          * @param data The data to be plotted.
  263.          *
  264.          * @return The CategoryPlot that can be attached to a JFreeChart instance.
  265.          */
  266.         public static PlotContainer createBoxPlot(final String title, final List<PlotData> data) {
  267.                 // To create a box plot, the dataset has to be put into a list (e.g. for
  268.                 // sorting purposes), so we iterate over the original list and create a new one for each selected attribute
  269.                 ArrayList<ArrayList<Double>> list = new ArrayList<ArrayList<Double>>();
  270.  
  271.                 // Create a type of dataset that can be used by a box (and whisker) plot and add the item to it
  272.                 DefaultBoxAndWhiskerCategoryDataset dataset = new DefaultBoxAndWhiskerCategoryDataset();
  273.  
  274.                 // Set up a renderer that paints the box plot
  275.                 BoxAndWhiskerRenderer boxRender = new BoxAndWhiskerRenderer();
  276.  
  277.                 // The plot
  278.                 PlotContainer plotContainer = null;
  279.  
  280.                 int height = 150;
  281.  
  282.                 // Iterate through all selected attribute columns ...
  283.                 for (int i = 0; i < data.size(); i++) {
  284.                         if (!data.get(i).name.contains("Result")) {
  285.                                 List<Double> attrData = data.get(i).getData();
  286.                                 // ..  and create a new dimension in the ArrayList ...
  287.                                 ArrayList<Double> newList = new ArrayList<Double>();
  288.                                 list.add(newList);
  289.                                 // ... and add all rows of the current column (i) to the second dimension
  290.                                 for (int j = 0; j < attrData.size(); j++) {
  291.                                         newList.add(attrData.get(j));
  292.                                 }
  293.                         }
  294.                 }
  295.  
  296.                 // For each selexted attribute ...
  297.                 for (int i = 0; i < data.size()-1; i++) {
  298.                         // .. create an object that will represent the standard box plot values (mean and quantiles) ...
  299.                         BoxAndWhiskerItem bwItem = BoxAndWhiskerCalculator.calculateBoxAndWhiskerStatistics(list.get(i));
  300.                         // ... and add it to the dataset
  301.                         dataset.add(bwItem, data.get(i+1).name, "");
  302.                 }
  303.  
  304.                 // The mean is quite ugly in visualization and not always part of a box plot... Disable it.
  305.                 boxRender.setMeanVisible(false);
  306.  
  307.                 // Also, add a tool tip generator activated by hovering over a single box plot
  308.                 boxRender.setBaseToolTipGenerator(new BoxAndWhiskerToolTipGenerator());
  309.  
  310.  
  311.                 // Create a CategoryPlot object with default axes and attached data
  312.                 CategoryPlot plot = new CategoryPlot(dataset, new CategoryAxis(), new NumberAxis(), boxRender);
  313.  
  314.                 // We like horizontal box plots ^v^
  315.                 plot.setOrientation(PlotOrientation.HORIZONTAL);
  316.  
  317.                 if (data.size() - 1 > 1 && data.size() - 1 < 7) {
  318.                         height = 100 * (data.size() - 1);
  319.                 }
  320.                 if (data.size() - 1 > 6) {
  321.                         height = 600;
  322.                 }
  323.  
  324.                 plotContainer = new PlotContainer(plot, data);
  325.                 plotContainer.height = height;
  326.  
  327.                 // Finally, return the plot
  328.                 return plotContainer;
  329.         }
  330.  
  331.         /**
  332.          * Creates a new CategoryPlot for drawing a Bar Plot.<br>
  333.          *
  334.          * <strong>Important:</strong> This plotting function is just implemented to create a bar plot with the ranking-results of the whole evaluation!
  335.          *
  336.          * @param title The title of the plot.
  337.          *
  338.          * @return The CategoryPlot that can be attached to a JFreeChart instance.
  339.          */
  340.         public static PlotContainer createBarPlot(final String title) {
  341.                 // Create a dataset that we can collect our evaluation results in
  342.                 DefaultCategoryDataset dataset = new DefaultCategoryDataset();
  343.  
  344.                 // Create a table model so we can show the evluation results
  345.                 DefaultTableModel dataTableModel = new DefaultTableModel(new String[]{"Algo", "Eval. algo", "Eval. Result"}, 0);
  346.                 JXTable dataTable = new JXTable(dataTableModel);
  347.  
  348.                 // Set up a renderer that paints this bar plot
  349.                 BarRenderer barRender = new BarRenderer();
  350.  
  351.                 // Iterate through all results...
  352.                 for (int algo = 0; algo < Current.results.size(); algo++) {
  353.                         Result result = Current.results.get(algo);
  354.                         // ... and if there are evaluations available for a result ...
  355.                         if (result.getNumberEvaluations() > 0) {
  356.                                 // ... add their values to the dataset and the table model
  357.                                 for (int i = 0; i < result.getNumberEvaluations(); i++) {
  358.                                         Tuple<String, Tuple<Double, PlotContainer>> eval = result.getEvaluation(i);
  359.                                         if (eval.second.first != null) {
  360.                                                 dataset.addValue(eval.second.first, algo + 1 + " - " + result.algorithm, i + 1 + " - " + eval.first);
  361.                                                 dataTableModel.addRow(new String[]{result.algorithm, eval.first, eval.second.first.toString()});
  362.                                         }
  363.                                 }
  364.                         }
  365.                 }
  366.  
  367.                 // Also, add tool tips
  368.                 barRender.setBaseToolTipGenerator(new StandardCategoryToolTipGenerator());
  369.  
  370.                 CategoryPlot plot = new CategoryPlot(dataset, new CategoryAxis(), new NumberAxis(), barRender);
  371.  
  372.                 // Finally, return the plot
  373.                 return new PlotContainer(plot, null, dataTable);
  374.         }
  375. }