[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