[Schmitzm-commits] r718 - in trunk: doc src/schmitzm/jfree/feature/style

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Mon Feb 22 22:38:12 CET 2010


Author: mojays
Date: 2010-02-22 22:38:10 +0100 (Mon, 22 Feb 2010)
New Revision: 718

Modified:
   trunk/doc/Chart style XML structure.pdf
   trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java
   trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java
   trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java
   trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java
   trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java
Log:
Aggregation functions for range attributes.
Chart documentation updated.

Modified: trunk/doc/Chart style XML structure.pdf
===================================================================
(Binary files differ)

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java	2010-02-22 17:26:18 UTC (rev 717)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureBasicChartStyle.java	2010-02-22 21:38:10 UTC (rev 718)
@@ -215,6 +215,42 @@
 		return dummyFeatureChartStyle.isAttributeNormalized(idx);
 	}
 
+    /** 
+     * Sets an arithmetical function which is calculated on
+     * the attribute values (when creating a {@link Dataset}
+     * from Features).
+     * The function is calculated on all values with the same
+     * domain value (X/category). If no function is set, duplicate
+     * domain values are ignored (only the "last" value is shown, because
+     * of replacement behavior).
+     * @param idx attribute index (1=1st range series;
+     *            2=2nd range series; ...)
+     * @param func defines the calculated function
+     * @exception IllegalArgumentException if function is set on
+     *            domain attribute (0)
+     */  
+	@Override
+    public void setAttributeAggregation(int idx, AggregationFunction func) {
+      dummyFeatureChartStyle.setAttributeAggregation(idx, func);
+    }
+      
+    /** 
+     * Returns an arithmetical function which is calculated on
+     * the attribute values (when creating a {@link Dataset}
+     * from Features).
+     * The function is calculated on all values with the same
+     * domain value (X/category). If no function is set, duplicate
+     * domain values are ignored (only the "last" value is shown, because
+     * of replacement behavior).
+     * @param idx attribute index (1=1st range series;
+     *            2=2nd range series; ...)
+     * @return {@code null} for index 0 (domain axis)
+     */  
+    @Override
+    public AggregationFunction getAttributeAggregation(int idx) {
+     return dummyFeatureChartStyle.getAttributeAggregation(idx); 
+    }
+
     /**
      * Sets the values, which are interpreted as "No Data". 
      * @param idx attribute index the "No Data" values are set for

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java	2010-02-22 17:26:18 UTC (rev 717)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartStyle.java	2010-02-22 21:38:10 UTC (rev 718)
@@ -29,6 +29,8 @@
  ******************************************************************************/
 package schmitzm.jfree.feature.style;
 
+import hep.aida.bin.StaticBin1D;
+
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -54,6 +56,52 @@
  */
 public interface FeatureChartStyle extends ChartStyle {
   /**
+   * Defines possible aggregation function to calculate 
+   * on attribute categories.
+   * @see FeatureChartStyle#setAttributeAggregation(int, AggregationFunction)
+   * @see FeatureChartStyle#getAttributeAggregation(int)
+   */
+  public static enum AggregationFunction {
+    /** Count of the attribute values. */
+    COUNT,
+    /** Sum of the attribute values. */
+    SUM,
+    /** Sum of the absolute attribute values. */
+    SUM_ABS,
+    /** Average of the attribute values. */
+    AVG,
+    /** Median of the attribute values. */
+    MEDIAN,
+    /** Minimum attribute value. */
+    MIN,
+    /** Maximum attribute value. */
+    MAX,
+    /** Variance of the attribute values. */
+    VARIANCE,
+    /** Standard deviation of the attribute values. */
+    STND_DEV;
+    
+    /**
+     * Returns the result of the function from a statistic.
+     * @param statistics Statistic to take the result from.
+     */
+    public Double getResult(StaticBin1D statistics) {
+      switch ( this ) {
+        case AVG: return statistics.mean();
+        case MAX: return statistics.max();
+        case MIN: return statistics.min();
+        case SUM: return statistics.sum();
+        case COUNT: return ((Integer)statistics.size()).doubleValue();
+        case STND_DEV: return statistics.standardDeviation();
+        case VARIANCE: return Math.pow(statistics.standardDeviation(),2);
+//        case SUM_ABS: return ??;
+//        case MEDIAN: return ??;
+      }
+      throw new UnsupportedOperationException("Aggregation function not yet supported: "+this);
+    }
+  }
+
+  /**
    * Returns the maximum number of feature attributes that can be
    * specified by this style.
    * @return -1 if there is no limit for range attributes
@@ -143,11 +191,40 @@
    * attribute (before creating a {@link Dataset}).
    * @param idx attribute index (0=domain; 1=1st range series;
    *            2=2nd range series; ...)
-   * @param normalize indicates the normalize property
    * @return {@code false} as default
    */  
   public boolean isAttributeNormalized(int idx);
   
+  /** 
+   * Sets an arithmetical function which is calculated on
+   * the attribute values (when creating a {@link Dataset}
+   * from Features).
+   * The function is calculated on all values with the same
+   * domain value (X/category). If no function is set, duplicate
+   * domain values are ignored (only the "last" value is shown, because
+   * of replacement behavior).
+   * @param idx attribute index (1=1st range series;
+   *            2=2nd range series; ...)
+   * @param func defines the calculated function
+   * @exception IllegalArgumentException if function is set on
+   *            domain attribute (0)
+   */  
+  public void setAttributeAggregation(int idx, AggregationFunction func);
+    
+  /** 
+   * Returns an arithmetical function which is calculated on
+   * the attribute values (when creating a {@link Dataset}
+   * from Features).
+   * The function is calculated on all values with the same
+   * domain value (X/category). If no function is set, duplicate
+   * domain values are ignored (only the "last" value is shown, because
+   * of replacement behavior).
+   * @param idx attribute index (1=1st range series;
+   *            2=2nd range series; ...)
+   * @return {@code null} for index 0 (domain axis)
+   */  
+  public AggregationFunction getAttributeAggregation(int idx);
+
   /**
    * Sets the values, which are interpreted as "No Data". 
    * @param idx attribute index the "No Data" values are set for
@@ -194,14 +271,13 @@
    */
   public <T> T filterNoDataValue(int idx, T value);
   
-	/**
-	 * Updates the unitVisible parameter for all axes at once.
-	 * 
-	 * @param visible
-	 *            <code>true</code> if unit string shall be displayed in the
-	 *            chart.
-	 */
-	public void setUnitVisible(boolean visible);
+  /**
+   * Updates the unitVisible parameter for all axes at once.
+   * @param visible
+   *            <code>true</code> if unit string shall be displayed in the
+   *            chart.
+   */
+  public void setUnitVisible(boolean visible);
 
   /**
    * This class defines a dummy implementation of {@link FeatureChartStyle} just
@@ -246,6 +322,9 @@
     /** Holds the "No Data" values for each attribute. */
     protected Map<Integer,Set<Object>> noDataValues = new HashMap<Integer, Set<Object>>();
 
+    /** Holds the aggregation function for each attribute. */
+    protected Map<Integer,AggregationFunction> aggrFuncs = new HashMap<Integer, AggregationFunction>();
+
     /**
      * Creates a new dummy. This constructor is protected so that only derived
      * classes can instantiate a dummy! There is no limit for the number
@@ -477,6 +556,46 @@
 	  return normalize != null && normalize;
 	}
 
+    /** 
+     * Sets an arithmetical function which is calculated on
+     * the attribute values (when creating a {@link Dataset}
+     * from Features).
+     * The function is calculated on all values with the same
+     * domain value (X/category). If no function is set, duplicate
+     * domain values are ignored (only the "last" value is shown, because
+     * of replacement behavior).
+     * @param idx attribute index (1=1st range series;
+     *            2=2nd range series; ...)
+     * @param func defines the calculated function
+     * @exception IllegalArgumentException if function is set on
+     *            domain attribute (0)
+     */  
+    @Override
+    public void setAttributeAggregation(int idx, AggregationFunction func) {
+      if ( idx == 0 )
+        throw new IllegalArgumentException("Aggregation function not allowed for attribute 0 (domain attribute)!");
+      aggrFuncs.put(idx, func);
+    }
+      
+    /** 
+     * Returns an arithmetical function which is calculated on
+     * the attribute values (when creating a {@link Dataset}
+     * from Features).
+     * The function is calculated on all values with the same
+     * domain value (X/category). If no function is set, duplicate
+     * domain values are ignored (only the "last" value is shown, because
+     * of replacement behavior).
+     * @param idx attribute index (1=1st range series;
+     *            2=2nd range series; ...)
+     * @return {@code null} for index 0 (domain axis)
+     */  
+    @Override
+    public AggregationFunction getAttributeAggregation(int idx) {
+     if ( idx == 0 )
+       return null;
+     return aggrFuncs.get(idx); 
+    }
+
     /**
      * Sets the values, which are interpreted as "No Data". 
      * @param idx attribute index the "No Data" values are set for

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java	2010-02-22 17:26:18 UTC (rev 717)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartStyleXMLFactory.java	2010-02-22 21:38:10 UTC (rev 718)
@@ -85,6 +85,9 @@
       rangeAttrNo++;
       chartStyle.setAttributeName(rangeAttrNo, featureAttrName);
       chartStyle.setAttributeNormalized(rangeAttrNo, XMLUtil.getBooleanAttribute(domainAttrElem, "normalize", false));
+      String aggrFuncStr = XMLUtil.getAttribute(domainAttrElem, "function", (String)null);
+      if ( aggrFuncStr != null )
+        chartStyle.setAttributeAggregation(rangeAttrNo, FeatureChartStyle.AggregationFunction.valueOf(aggrFuncStr) );
     }
   }
 
@@ -133,7 +136,8 @@
     for (int i=1; i<style.getAttributeCount(); i++)
       addChildToElement(attrElem, "rangeAttr", false,
           "name", style.getAttributeName(i),
-          "normalize", style.isAttributeNormalized(i)
+          "normalize", style.isAttributeNormalized(i),
+          "function", style.getAttributeAggregation(i)
       );
 
     return root;

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java	2010-02-22 17:26:18 UTC (rev 717)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureChartUtil.java	2010-02-22 21:38:10 UTC (rev 718)
@@ -251,6 +251,12 @@
 		// Calculate any statistics needed for normalization.
 		HashMap<String, StaticBin1D> statisticsForNormalization = calcStatisticsForNormalization(
 				fc, chartStyle);
+        // Prepare set for statistics to calculate aggregation
+		// functions (one statistic for each range attribute of
+		// each domain value)
+        HashMap<Number, StaticBin1D>[] statisticsForAggregation = new HashMap[attrCount];
+        for (int i=1; i<attrCount; i++)
+          statisticsForAggregation[i] = new HashMap<Number, StaticBin1D>();
 
 		// If dataset should be sorted, the features must be sorted first
 		// according to the domain attribute. The "autoSort" functionality
@@ -307,13 +313,45 @@
 					yValue = normalize(yValue, yAttrName,
 							statisticsForNormalization);
 
-				xySeries[attrIdx].add(xValue, yValue);
-
-				// Mapping between FID and data index in series
-				mapping.setMapping(f.getID(), yAttrName, datasetIdx++);
+				// Fill series, if no aggregation function is defined.
+				// Otherwise fill statistic (dataset is filled later!)
+				if ( chartStyle.getAttributeAggregation(attrIdx) == null ) {
+				  // Fill series
+				  xySeries[attrIdx].add(xValue, yValue);
+				  // Mapping between FID and data index in series
+				  mapping.setMapping(f.getID(), yAttrName, datasetIdx++);
+				} else {
+				  StaticBin1D aggrStat = statisticsForAggregation[attrIdx].get(xValue);
+				  if ( aggrStat == null ) {
+				    aggrStat = new DynamicBin1D();
+				    statisticsForAggregation[attrIdx].put(xValue, aggrStat);
+				  }
+				  aggrStat.add(yValue.doubleValue());
+				  // TODO: Mapping vormerken (??)
+				  // Problem: siehe unten
+				}
 			}
-
 		}
+		
+		// Fill series for aggregated range attributes
+        for (int attrIdx = 1; attrIdx < attrCount; attrIdx++) {
+          String yAttrName = chartStyle.getAttributeName(attrIdx);
+          FeatureChartStyle.AggregationFunction aggrFunc = chartStyle.getAttributeAggregation(attrIdx);
+          if ( aggrFunc == null )
+            continue;
+          for (Number xValue : statisticsForAggregation[attrIdx].keySet() ) {
+            StaticBin1D aggrStat = statisticsForAggregation[attrIdx].get(xValue);
+            Number      yValue   = aggrFunc.getResult(aggrStat); 
+            // Fill series
+            xySeries[attrIdx].add(xValue, yValue);
+            // TODO: Mapping setzen
+            // Problem: Pro dataset item kann nur EINE FeatureID gesetzt
+            //          werden (Feature2DatasetMapping, Zeile 124) 
+//            // Mapping between FID and data index in series
+//            mapping.setMapping(f.getID() ??, yAttrName, datasetIdx++);
+          }
+        }
+		
 		return dataset;
 	}
 
@@ -367,7 +405,7 @@
 							String attrName = chartStyle
 									.getAttributeName(attrIdx);
 
-							// SK: Since normalization is now usaually set for
+							// SK: Since normalization is now usually set for
 							// all
 							// attributes (even when they are not numeric), we
 							// double check here, whether it is really a numeric
@@ -470,6 +508,12 @@
 		// Calculate any statistics needed for normalization.
 		HashMap<String, StaticBin1D> statisticsForNormalization = calcStatisticsForNormalization(
 				fc, chartStyle);
+        // Prepare set for statistics to calculate aggregation
+        // functions (one statistic for each range attribute of
+        // each domain value)
+        HashMap<Comparable<?>, StaticBin1D>[] statisticsForAggregation = new HashMap[attrCount];
+        for (int i=1; i<attrCount; i++)
+          statisticsForAggregation[i] = new HashMap<Comparable<?>, StaticBin1D>();
 
 		// Create a new dataset and insert the series
 		DefaultCategoryDataset dataset = new DefaultCategoryDataset();
@@ -523,14 +567,45 @@
 						yValue = normalize(yValue, yAttrName,
 								statisticsForNormalization);
 
-					// Add data to dataset
-					dataset.addValue(yValue, yAttrName, catValue);
-
-					// Mapping between FID and data index in series
-					mapping.setMapping(f.getID(), yAttrName, catValue);
+	                // Fill series, if no aggregation function is defined.
+	                // Otherwise fill statistic (dataset is filled later!)
+	                if ( chartStyle.getAttributeAggregation(attrIdx) == null ) {
+	                  // Add data to dataset
+	                  dataset.addValue(yValue, yAttrName, catValue);
+	                  // Mapping between FID and data index in series
+	                  mapping.setMapping(f.getID(), yAttrName, catValue);
+	                } else {
+	                  StaticBin1D aggrStat = statisticsForAggregation[attrIdx].get(catValue);
+	                  if ( aggrStat == null ) {
+	                    aggrStat = new DynamicBin1D();
+	                    statisticsForAggregation[attrIdx].put(catValue, aggrStat);
+	                  }
+	                  aggrStat.add(yValue.doubleValue());
+	                  // TODO: Mapping vormerken (??)
+	                  // Problem: siehe unten
+	                }
 				}
 
 			}
+
+		     // Fill series for aggregated range attributes
+	        for (int attrIdx = 1; attrIdx < attrCount; attrIdx++) {
+	          String yAttrName = chartStyle.getAttributeName(attrIdx);
+	          FeatureChartStyle.AggregationFunction aggrFunc = chartStyle.getAttributeAggregation(attrIdx);
+	          if ( aggrFunc == null )
+	            continue;
+	          for (Comparable<?> catValue : statisticsForAggregation[attrIdx].keySet() ) {
+	            StaticBin1D aggrStat = statisticsForAggregation[attrIdx].get(catValue);
+	            Number      yValue   = aggrFunc.getResult(aggrStat); 
+	            // Fill series
+                dataset.addValue(yValue, yAttrName, catValue);
+	            // TODO: Mapping setzen
+	            // Problem: Pro dataset item kann nur EINE FeatureID gesetzt
+	            //          werden (Feature2DatasetMapping, Zeile 124) 
+//	            // Mapping between FID and data index in series
+//	            mapping.setMapping(f.getID() ??, yAttrName, datasetIdx++);
+	          }
+	        }
 		} finally {
 			if (features != null) {
 				// this is a hint

Modified: trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java
===================================================================
--- trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java	2010-02-22 17:26:18 UTC (rev 717)
+++ trunk/src/schmitzm/jfree/feature/style/FeatureScatterChartStyle.java	2010-02-22 21:38:10 UTC (rev 718)
@@ -41,6 +41,7 @@
 
 import schmitzm.jfree.chart.style.ChartStyle;
 import schmitzm.jfree.chart.style.ScatterChartStyle;
+import schmitzm.jfree.feature.style.FeatureChartStyle.AggregationFunction;
 
 /**
  * This class extends the {@link ScatterChartStyle} with the properties
@@ -230,6 +231,42 @@
        return dummyFeatureChartStyle.isAttributeNormalized(idx);
   }
 
+  /** 
+   * Sets an arithmetical function which is calculated on
+   * the attribute values (when creating a {@link Dataset}
+   * from Features).
+   * The function is calculated on all values with the same
+   * domain value (X/category). If no function is set, duplicate
+   * domain values are ignored (only the "last" value is shown, because
+   * of replacement behavior).
+   * @param idx attribute index (1=1st range series;
+   *            2=2nd range series; ...)
+   * @param func defines the calculated function
+   * @exception IllegalArgumentException if function is set on
+   *            domain attribute (0)
+   */  
+  @Override
+  public void setAttributeAggregation(int idx, AggregationFunction func) {
+    dummyFeatureChartStyle.setAttributeAggregation(idx, func);
+  }
+    
+  /** 
+   * Returns an arithmetical function which is calculated on
+   * the attribute values (when creating a {@link Dataset}
+   * from Features).
+   * The function is calculated on all values with the same
+   * domain value (X/category). If no function is set, duplicate
+   * domain values are ignored (only the "last" value is shown, because
+   * of replacement behavior).
+   * @param idx attribute index (1=1st range series;
+   *            2=2nd range series; ...)
+   * @return {@code null} for index 0 (domain axis)
+   */
+  @Override
+  public AggregationFunction getAttributeAggregation(int idx) {
+   return dummyFeatureChartStyle.getAttributeAggregation(idx); 
+  }
+
   /**
    * Sets the values, which are interpreted as "No Data". 
    * @param idx attribute index the "No Data" values are set for



More information about the Schmitzm-commits mailing list