[Schmitzm-commits] r1202 - in trunk: src/schmitzm/jfree src/schmitzm/jfree/chart/style src/schmitzm/jfree/data src/schmitzm/jfree/resource/locales src_junit/schmitzm/jfree/feature/style

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Tue Nov 2 23:21:30 CET 2010


Author: mojays
Date: 2010-11-02 23:21:30 +0100 (Tue, 02 Nov 2010)
New Revision: 1202

Modified:
   trunk/src/schmitzm/jfree/JFreeChartUtil.java
   trunk/src/schmitzm/jfree/chart/style/ScatterChartStyle.java
   trunk/src/schmitzm/jfree/data/RegressionDataset.java
   trunk/src/schmitzm/jfree/data/RegressionDatasetImpl.java
   trunk/src/schmitzm/jfree/resource/locales/JFreeResourceBundle.properties
   trunk/src/schmitzm/jfree/resource/locales/JFreeResourceBundle_de.properties
   trunk/src_junit/schmitzm/jfree/feature/style/FeatureChartStyleTest.java
Log:
textual regression information (r, n and formula) in plot

Modified: trunk/src/schmitzm/jfree/JFreeChartUtil.java
===================================================================
--- trunk/src/schmitzm/jfree/JFreeChartUtil.java	2010-11-02 20:26:42 UTC (rev 1201)
+++ trunk/src/schmitzm/jfree/JFreeChartUtil.java	2010-11-02 22:21:30 UTC (rev 1202)
@@ -31,6 +31,7 @@
 
 import java.awt.BasicStroke;
 import java.awt.Color;
+import java.awt.Font;
 import java.awt.Stroke;
 import java.text.DecimalFormat;
 import java.util.HashMap;
@@ -40,12 +41,14 @@
 import org.apache.log4j.Logger;
 import org.jfree.chart.JFreeChart;
 import org.jfree.chart.LegendItemSource;
+import org.jfree.chart.annotations.XYTitleAnnotation;
 import org.jfree.chart.axis.Axis;
 import org.jfree.chart.axis.NumberAxis;
 import org.jfree.chart.axis.ValueAxis;
 import org.jfree.chart.block.BlockBorder;
 import org.jfree.chart.block.BlockContainer;
 import org.jfree.chart.block.BorderArrangement;
+import org.jfree.chart.block.ColumnArrangement;
 import org.jfree.chart.block.EmptyBlock;
 import org.jfree.chart.event.PlotChangeEvent;
 import org.jfree.chart.event.PlotChangeListener;
@@ -79,22 +82,22 @@
 import org.jfree.chart.renderer.xy.XYStepRenderer;
 import org.jfree.chart.title.CompositeTitle;
 import org.jfree.chart.title.LegendTitle;
+import org.jfree.chart.title.TextTitle;
 import org.jfree.chart.title.Title;
 import org.jfree.chart.urls.StandardXYURLGenerator;
 import org.jfree.chart.urls.XYURLGenerator;
 import org.jfree.data.Range;
 import org.jfree.data.UnknownKeyException;
 import org.jfree.data.category.CategoryDataset;
-import org.jfree.data.function.Function2D;
-import org.jfree.data.function.LineFunction2D;
 import org.jfree.data.general.Dataset;
-import org.jfree.data.general.DatasetUtilities;
 import org.jfree.data.general.PieDataset;
 import org.jfree.data.time.TimeSeries;
 import org.jfree.data.time.TimeSeriesCollection;
 import org.jfree.data.xy.XYDataset;
 import org.jfree.data.xy.XYSeries;
 import org.jfree.data.xy.XYSeriesCollection;
+import org.jfree.ui.HorizontalAlignment;
+import org.jfree.ui.RectangleAnchor;
 import org.jfree.ui.RectangleEdge;
 import org.jfree.ui.RectangleInsets;
 
@@ -1022,18 +1025,21 @@
 			if ((xySeriesCollection.getSeriesCount() > 0) && (xySeriesCollection.getItemCount(0) >= 2)) {
 				// create sample data for curve (plot function directly is not
 				// yet available)
-				XYDataset regressionData = createRegressionLineDataset(
+				RegressionDataset regressionData = createRegressionLineDataset(
 						(XYSeriesCollection) dataset, 0, title
 								+ " "+RESOURCE.getString("regressionline"), 2);
-				if (regressionData != null)
+				if (regressionData != null) {
 					addRegressionLineToPlot(plot, regressionData, Color.blue);
+					addRegressionInfoToPlot(plot, regressionData);
+				}
 			} else {
 				LOGGER
 						.info("Not enought items in the series to create a regression line.");
 			}
 		}
+		
 		JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT,
-				plot, true);
+		    plot, true);
 
 		return chart; // ChartFactory.createScatterPlot(title, xAttr, yAttr,
 		// dataset, PlotOrientation.HORIZONTAL, true, true,
@@ -1109,7 +1115,7 @@
 		double xbar = sumX / n;
 		double ybar = sumY / n;
 
-		double[] result = new double[3];
+		double[] result = new double[4];
 		result[1] = sxy / sxx;
 		result[0] = ybar - result[1] * xbar;
 		
@@ -1118,6 +1124,7 @@
 				/ Math.sqrt((n * sumXsq - sumX * sumX)
 						* (n * sumYsq - sumY * sumY));
 
+		result[3] = n;
 		return result;
 
 	}
@@ -1228,7 +1235,7 @@
 	 *            the color for the regression line
 	 */
 	public static void addRegressionLineToPlot(XYPlot plot,
-			XYDataset regressionData, Color lineColor) {
+			RegressionDataset regressionData, Color lineColor) {
 		int datasetCount = plot.getDatasetCount();
 		// set the regression data
 		plot.setDataset(datasetCount, regressionData);
@@ -1245,10 +1252,78 @@
 		});
 		renderer.setSeriesPaint(0, Color.blue);
 		plot.setRenderer(datasetCount, renderer);
-		
-		// TODO Ich will einen schönen Tooltip für die Regressionslinine in der Legende
 	}
+	
+    /**
+     * Adds annotations to a plot which contains textual informations
+     * about the regression.
+     * 
+     * @param plot
+     *            the plot the annotation is added to (at top left)
+     * @param regressionData
+     *            the regression data
+     */
+	public static void addRegressionInfoToPlot(XYPlot plot, RegressionDataset regressionData) {
+      DecimalFormat formatter = new DecimalFormat("0.000");
+      
+      // Container which hold the title and text
+      BlockContainer container = new BlockContainer( new ColumnArrangement() );
+      
+      // Information title
+      String regrInfoTitleStr = R("regressionInfo.title") + ":";
+      TextTitle regrInfoTitle = new TextTitle(regrInfoTitleStr, TextTitle.DEFAULT_FONT.deriveFont(Font.BOLD) );
+      regrInfoTitle.setTextAlignment(HorizontalAlignment.LEFT);
+      container.add(regrInfoTitle);
+      
+      // Information text for R
+      String regrInfoRStr = R("regressionInfo.data.r");
+      regrInfoRStr += " = " + formatter.format(regressionData.getR());
+      regrInfoRStr += " (" + regressionData.getRQuality() + ")";
+      TextTitle regrInfoR = new TextTitle(regrInfoRStr, TextTitle.DEFAULT_FONT.deriveFont(Font.PLAIN) );
+      regrInfoR.setTextAlignment(HorizontalAlignment.LEFT);
+      regrInfoR.setToolTipText(R("regressionInfo.data.r") + " = " + regressionData.getR() );
+      container.add(regrInfoR);
+      
+      // Information text for N
+      String regrInfoNStr = R("regressionInfo.data.n");
+      regrInfoNStr += " = " + regressionData.getSampleCount();
+      TextTitle regrInfoN = new TextTitle(regrInfoNStr, TextTitle.DEFAULT_FONT.deriveFont(Font.PLAIN) );
+      regrInfoN.setTextAlignment(HorizontalAlignment.LEFT);
+      regrInfoN.setToolTipText(R("regressionInfo.data.count") + " = " + regressionData.getSampleCount() );
+      container.add(regrInfoN);
 
+      // Information text for the regression line formular
+      String regrInfoFormulaStr = R("regressionInfo.data.formula");
+      regrInfoFormulaStr += " = " + formatter.format(regressionData.getRegressionLineSlope()) + "x";
+      regrInfoFormulaStr += ( regressionData.getRegressionLineIntercept() >= 0 ? "  + " : "  - " );
+      regrInfoFormulaStr += formatter.format(Math.abs(regressionData.getRegressionLineIntercept()));
+      TextTitle regrInfoFormula = new TextTitle(regrInfoFormulaStr, TextTitle.DEFAULT_FONT.deriveFont(Font.PLAIN) );
+      regrInfoFormula.setTextAlignment(HorizontalAlignment.LEFT);
+      regrInfoFormula.setToolTipText(
+          R("regressionInfo.data.slope") + " = " + regressionData.getRegressionLineSlope() +
+          "; " +
+          R("regressionInfo.data.intercept") + " = " + regressionData.getRegressionLineIntercept()
+      );
+      container.add(regrInfoFormula);
+
+      // Create a Title for the BlockContainer
+      CompositeTitle compTitle = new CompositeTitle(container);
+      
+      // Create the Annotation and add it to the plot
+      XYTitleAnnotation regrInfoAnno = null;
+      if ( regressionData.getRegressionLineSlope() >= 0 )
+        // if slope is positive, the regression line is plot
+        // from bottom left to top right, so put the information
+        // on the top left site of the plot
+        regrInfoAnno = new XYTitleAnnotation(0.02, 0.98, compTitle, RectangleAnchor.TOP_LEFT);
+      else
+        // if slope is negative, the regression line is plot
+        // from top left to bottom right, so put the information
+        // on the bottom left site of the plot
+        regrInfoAnno = new XYTitleAnnotation(0.02, 0.02, compTitle, RectangleAnchor.BOTTOM_LEFT);
+      plot.addAnnotation( regrInfoAnno );
+	}
+
 	
 	/**
      * Creates a basic stroke by only some basic attributes

Modified: trunk/src/schmitzm/jfree/chart/style/ScatterChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/chart/style/ScatterChartStyle.java	2010-11-02 20:26:42 UTC (rev 1201)
+++ trunk/src/schmitzm/jfree/chart/style/ScatterChartStyle.java	2010-11-02 22:21:30 UTC (rev 1202)
@@ -39,6 +39,7 @@
 import org.jfree.data.xy.XYSeriesCollection;
 
 import schmitzm.jfree.JFreeChartUtil;
+import schmitzm.jfree.data.RegressionDataset;
 import schmitzm.lang.LangUtil;
 
 /**
@@ -146,11 +147,13 @@
       // -> plot function directly is not yet available in JFreeChart
       XYSeriesCollection dataset         = (XYSeriesCollection)chart.getXYPlot().getDataset();
       String             regressionTitle = getTitleStyle().getLabel() + " Regression line"; //i8n
-      XYDataset          regressionData  = JFreeChartUtil.createRegressionLineDataset(
+      RegressionDataset  regressionData  = JFreeChartUtil.createRegressionLineDataset(
                                                  dataset, 0, regressionTitle, 2);
       // Add regression line to plot (with default color)
-      if ( regressionData != null )
+      if ( regressionData != null ) {
         JFreeChartUtil.addRegressionLineToPlot(chart.getXYPlot(), regressionData, Color.blue);
+        JFreeChartUtil.addRegressionInfoToPlot(chart.getXYPlot(), regressionData);
+      }
     }
 
     // apply "normal" style properties

Modified: trunk/src/schmitzm/jfree/data/RegressionDataset.java
===================================================================
--- trunk/src/schmitzm/jfree/data/RegressionDataset.java	2010-11-02 20:26:42 UTC (rev 1201)
+++ trunk/src/schmitzm/jfree/data/RegressionDataset.java	2010-11-02 22:21:30 UTC (rev 1202)
@@ -77,6 +77,12 @@
   public double getRegressionLineIntercept();
 
   /**
+   * Returns the number of samples the regression calculation bases
+   * on.
+   */
+  public int getSampleCount();
+
+  /**
    * Returns the regression line for the dataset.
    */
   public Function2D getRegressionLine();

Modified: trunk/src/schmitzm/jfree/data/RegressionDatasetImpl.java
===================================================================
--- trunk/src/schmitzm/jfree/data/RegressionDatasetImpl.java	2010-11-02 20:26:42 UTC (rev 1201)
+++ trunk/src/schmitzm/jfree/data/RegressionDatasetImpl.java	2010-11-02 22:21:30 UTC (rev 1202)
@@ -46,6 +46,9 @@
  * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
  */
 public class RegressionDatasetImpl extends PipedXYDataset implements RegressionDataset {
+  /** Holds the number of data items the regression calculation
+   *  bases on. */
+  protected int      dataCount = 0;
   /** Holds the R value of the regression. */
   protected double   rValue = 0.0;
   /** Holds the coefficients of the regression line (0 = intercept, 1 = slope). */
@@ -80,6 +83,7 @@
     double[] coefficients = JFreeChartUtil.getOLSRegression(dataset, series);
     Function2D curve      = new LineFunction2D(coefficients[0], coefficients[1]);
     double     r          = coefficients[2];
+    int        dataCount  = (int)coefficients[3];
     
     // Put additional legend informations in series key
     // NOTE: The KECK projects parses this information!!
@@ -96,6 +100,7 @@
     regrDataset.regrLine = curve;
     regrDataset.olsCoefficients = new double[] {coefficients[0], coefficients[1]};
     regrDataset.rValue = r;
+    regrDataset.dataCount = dataCount;
         
     return regrDataset;
   }
@@ -118,6 +123,14 @@
   }
 
   /**
+   * Returns the number of samples the regression calculation bases
+   * on.
+   */
+  public int getSampleCount() {
+    return dataCount;
+  }
+
+  /**
    * Returns the 2 regression coefficients: [0] = the intercept; [1] = the slope
    * <b>Note</b>: Each call returns a new array instance!
    */

Modified: trunk/src/schmitzm/jfree/resource/locales/JFreeResourceBundle.properties
===================================================================
--- trunk/src/schmitzm/jfree/resource/locales/JFreeResourceBundle.properties	2010-11-02 20:26:42 UTC (rev 1201)
+++ trunk/src/schmitzm/jfree/resource/locales/JFreeResourceBundle.properties	2010-11-02 22:21:30 UTC (rev 1202)
@@ -94,4 +94,12 @@
 
 regressionline.tooltip=<html><i>r</i> is the product-moment-correlation coefficient and gives information about how strong the variables are related.</html>
 
+regressionInfo.title=Regression information
+regressionInfo.data.r=r
+regressionInfo.data.n=n
+regressionInfo.data.count=Number of samples in the regression
+regressionInfo.data.formula=Formula (ax + b)
+regressionInfo.data.slope=Slope
+regressionInfo.data.intercept=Intercept
+
 Exception.noWeightAttributeDefinedforAWeightedAggregation=A weighted AggregationFunction is selected, but not artribute for weighting is selected.

Modified: trunk/src/schmitzm/jfree/resource/locales/JFreeResourceBundle_de.properties
===================================================================
--- trunk/src/schmitzm/jfree/resource/locales/JFreeResourceBundle_de.properties	2010-11-02 20:26:42 UTC (rev 1201)
+++ trunk/src/schmitzm/jfree/resource/locales/JFreeResourceBundle_de.properties	2010-11-02 22:21:30 UTC (rev 1202)
@@ -96,5 +96,14 @@
 regression.total.neg=vollkommener negativer Zusammenhang
 
 regressionline.tooltip=<html><i>r</i> ist der Produktmomentkorrelationskoefizient und sagt aus, wie stark zwei Variablen voneinander abh\u00E4ngen. 
+
+regressionInfo.title=Regressions-Daten
+regressionInfo.data.r=r
+regressionInfo.data.n=n
+regressionInfo.data.count=Anzahl der Wertepaare in der Regression
+regressionInfo.data.formula=Formel (ax + b)
+regressionInfo.data.slope=Steigung
+regressionInfo.data.intercept=Y-Abschnitt
+
 Exception.noWeightAttributeDefinedforAWeightedAggregation=Eine gewichtete Aggregierungsfunktion ist ausgew\u00E4hlt, aber kein Attribut f\u00FCr die Gewichtung.
 

Modified: trunk/src_junit/schmitzm/jfree/feature/style/FeatureChartStyleTest.java
===================================================================
--- trunk/src_junit/schmitzm/jfree/feature/style/FeatureChartStyleTest.java	2010-11-02 20:26:42 UTC (rev 1201)
+++ trunk/src_junit/schmitzm/jfree/feature/style/FeatureChartStyleTest.java	2010-11-02 22:21:30 UTC (rev 1202)
@@ -474,11 +474,10 @@
 	                "testScatterChart");
 	  ChartPlotStyle plotStyle = new ChartPlotStyle();
 	  chartStyle.setPlotStyle(plotStyle);
-      chartStyle.setPlotStyle(plotStyle);
 	  chartStyle.setAttributeName(0, attr1Name);
 	  chartStyle.setAttributeName(1, attr2Name);
-	  chartStyle.getPlotStyle().setCenterOriginSymetrically(true);
-      chartStyle.getPlotStyle().setCrosshairVisible(true);
+//	  chartStyle.getPlotStyle().setCenterOriginSymetrically(true);
+//      chartStyle.getPlotStyle().setCrosshairVisible(true);
 
 	  JFreeChart chart = chartStyle.applyToFeatureCollection(testFeatures);
 	  assertNotNull("applyToFeatureCollection lieferte null!", chart);



More information about the Schmitzm-commits mailing list