Mercurial > dive4elements > gnv-client
diff gnv-artifacts/src/main/java/de/intevation/gnv/chart/DefaultHistogram.java @ 1119:7c4f81f74c47
merged gnv-artifacts
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:00 +0200 |
parents | f953c9a559d8 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/chart/DefaultHistogram.java Fri Sep 28 12:14:00 2012 +0200 @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2010 by Intevation GmbH + * + * This program is free software under the LGPL (>=v2.1) + * Read the file LGPL.txt coming with the software for details + * or visit http://www.gnu.org/licenses/ if it does not exist. + */ + +package de.intevation.gnv.chart; + +import java.util.Locale; +import java.util.Map; + +import org.apache.log4j.Logger; + +import org.jfree.chart.ChartTheme; + +import org.jfree.chart.plot.XYPlot; + +/** + * Default implementation of {@link de.intevation.gnv.chart.AbstractHistogram}. + * + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class DefaultHistogram +extends AbstractHistogram +{ + /** + * Default bin count. + * TODO find a better default value + */ + public static final int DEFAULT_BINS = 15; + + /** + * Constant field for limitating the number of bin in a single histogram. + */ + public static final int MAXIMAL_BINS = 20; + + /** + * Default key to retrieve the number of bins from {@link + * #requestParameter}. + */ + public static final String REQUEST_KEY_BIN_COUNT = "bincount"; + + /** + * Default key to retrieve the width of a single bin from {@link + * #requestParameter}. + */ + public static final String REQUEST_KEY_BIN_WIDTH = "binwidth"; + + /** + * Default key to retrieve the chart width from {@link #requestParameter}. + */ + public static final String REQUEST_KEY_CHART_WIDTH = "width"; + + /** + * Default key to retrieve the object from {@link #requestParameter}. It + * defines which value this chart has to be used for bin calculation. You + * can either adjust the number of bins or the width of a single bin. + */ + public static final String REQUEST_KEY_BIN_CHOICE = "bintype"; + + /** + * Logger used for logging with log4j. + */ + private static Logger logger = Logger.getLogger(DefaultHistogram.class); + + /** + * Object storing some further parameter used for chart settings. + */ + protected Map requestParameter; + + protected double[] minmax = null; + + + /** + * Constructor to create DefaultHistogram objects. + * + * @param labels Labels to decorate this chart. + * @param data Raw data to be displayed in histogram. + * @param theme Theme used to adjust the chart look. + * @param requestParameter Object which serves some further settings. + */ + public DefaultHistogram( + ChartLabels labels, Object[] data, ChartTheme theme, Map requestParameter + ) { + super(labels, data, theme); + this.requestParameter = requestParameter; + this.locale = (Locale) requestParameter.get("locale"); + } + + + @Override + protected void applyDatasets() { + XYPlot plot = (XYPlot) chart.getPlot(); + + // prepare data and create add them to histogram dataset + String name = (String) data[0]; + double[] values = toDouble((Double[]) data[1]); + + double binWidth = getBinWidth(values); + int binCount = getBinCount(); + + AdvancedHistogramDataset dataset = + new AdvancedHistogramDataset(binCount, binWidth); + dataset.addSeries(name, values); + + plot.setDataset(0, dataset); + } + + + /** + * Method which scans the hole bunch of values and returns an array with + * contains min and max value. Min value is stored at position 0, max value + * is stored at position 1 in that array. + * + * @param values Array which contains all values + * + * @return Array which contains min and max value + */ + protected double[] getMinMax(double[] values) { + if (minmax != null) + return minmax; + + double[] minmax = new double[2]; + minmax[0] = Double.MAX_VALUE; + minmax[1] = Double.MIN_VALUE; + + int length = values.length; + for (int i = 0; i < length; i++) { + minmax[0] = values[i] < minmax[0] ? values[i] : minmax[0]; + minmax[1] = values[i] > minmax[1] ? values[i] : minmax[1]; + } + + this.minmax = minmax; + + return minmax; + } + + + /** + * Turn a Double[] into a double[]. + * + * @param array Doube[] + * + * @return double[] + */ + protected double[] toDouble(Double[] array) { + int length = array.length; + double[] values = new double[length]; + + for(int i = 0; i < length; i++) { + values[i] = array[i].doubleValue(); + } + + return values; + } + + + /** + * Method to retrieve the number of bins. + * + * @return the number of bins that is specified in <i>requestParameter</i> + * or -1 if the number of bins is not the dominant value to calculate the + * width of a single bin. + */ + protected int getBinCount() { + // Return -1 to trigger a calculation of the number of bins in + // AdvancedHistogramDataset if the user chose the bin width as dominant + // value. + String choice = (String) requestParameter.get(REQUEST_KEY_BIN_CHOICE); + if (choice != null && choice.equalsIgnoreCase(REQUEST_KEY_BIN_WIDTH)) { + return -1; + } + + int bins = -1; + String param = (String) requestParameter.get(REQUEST_KEY_BIN_COUNT); + + try { + bins = Integer.parseInt(param); + bins = bins <= 0 ? DEFAULT_BINS : bins; + bins = bins > MAXIMAL_BINS ? MAXIMAL_BINS : bins; + + return bins; + } + catch (NumberFormatException nfe) { + logger.warn("Invalid number of bins for histogram chart: " + param); + logger.warn("Return default bins: " + DEFAULT_BINS); + + return DEFAULT_BINS; + } + } + + + /** + * Serves width of a single bin. + * + * @param values All values in this histogram + * + * @return The bin width that is given in <i>requestParameter</i> or -1 if + * the bin width is not the dominant value for calculating the number of + * bins in the histogram. + */ + protected double getBinWidth(double[] values) { + // Return -1 to trigger a calculation of the bin width in + // AdvancedHistogramDataset if the user chose the number of bins as + // dominant value. + String choice = (String) requestParameter.get(REQUEST_KEY_BIN_CHOICE); + if (choice == null || !choice.equalsIgnoreCase(REQUEST_KEY_BIN_WIDTH)) { + return -1; + } + + int bins = -1; + String param = (String) requestParameter.get(REQUEST_KEY_BIN_WIDTH); + + double[] minmax = getMinMax(values); + double totalWidth = minmax[1] - minmax[0]; + double binWidth = Double.parseDouble(param); + + double tmpBins = totalWidth / binWidth; + + bins = (int) Math.round(tmpBins); + bins = bins <= 0 ? DEFAULT_BINS : bins; + + // the calculated number of bins with the given width exceed the maximum + // number of bins. + if (bins > MAXIMAL_BINS) { + return totalWidth / (MAXIMAL_BINS); + } + + return binWidth; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :