comparison gnv-artifacts/src/main/java/de/intevation/gnv/chart/DefaultHistogram.java @ 1055:bb2679624c6a

Implemented a new histogram dataset that takes the width of a single bin as well as the number of bins for the histogram (issue288). gnv-artifacts/trunk@1130 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Thu, 27 May 2010 07:41:14 +0000
parents 8430269ec73b
children 86ca3c10523f
comparison
equal deleted inserted replaced
1054:8430269ec73b 1055:bb2679624c6a
1 package de.intevation.gnv.chart; 1 package de.intevation.gnv.chart;
2 2
3 import java.text.NumberFormat;
4 import java.text.ParseException;
5
6 import java.util.Locale;
7 import java.util.Map; 3 import java.util.Map;
8 4
9 import org.apache.log4j.Logger; 5 import org.apache.log4j.Logger;
10 6
11 import org.jfree.chart.ChartTheme; 7 import org.jfree.chart.ChartTheme;
12 8
13 import org.jfree.chart.plot.XYPlot; 9 import org.jfree.chart.plot.XYPlot;
14
15 import org.jfree.data.statistics.HistogramDataset;
16 10
17 /** 11 /**
18 * Default implementation of {@link de.intevation.gnv.chart.AbstractHistogram}. 12 * Default implementation of {@link de.intevation.gnv.chart.AbstractHistogram}.
19 * 13 *
20 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> 14 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
65 /** 59 /**
66 * Object storing some further parameter used for chart settings. 60 * Object storing some further parameter used for chart settings.
67 */ 61 */
68 protected Map requestParameter; 62 protected Map requestParameter;
69 63
64 protected double[] minmax = null;
65
70 66
71 /** 67 /**
72 * Constructor to create DefaultHistogram objects. 68 * Constructor to create DefaultHistogram objects.
73 * 69 *
74 * @param labels Labels to decorate this chart. 70 * @param labels Labels to decorate this chart.
89 XYPlot plot = (XYPlot) chart.getPlot(); 85 XYPlot plot = (XYPlot) chart.getPlot();
90 86
91 // prepare data and create add them to histogram dataset 87 // prepare data and create add them to histogram dataset
92 String name = (String) data[0]; 88 String name = (String) data[0];
93 double[] values = toDouble((Double[]) data[1]); 89 double[] values = toDouble((Double[]) data[1]);
94 int bins = getBinCount(values); 90
95 91 double binWidth = getBinWidth(values);
96 HistogramDataset dataset = new HistogramDataset(); 92 int binCount = getBinCount();
97 dataset.addSeries(name, values, bins); 93
94 AdvancedHistogramDataset dataset =
95 new AdvancedHistogramDataset(binCount, binWidth);
96 dataset.addSeries(name, values);
98 97
99 plot.setDataset(0, dataset); 98 plot.setDataset(0, dataset);
100 } 99 }
101 100
102 101
108 * @param values Array which contains all values 107 * @param values Array which contains all values
109 * 108 *
110 * @return Array which contains min and max value 109 * @return Array which contains min and max value
111 */ 110 */
112 protected double[] getMinMax(double[] values) { 111 protected double[] getMinMax(double[] values) {
112 if (minmax != null)
113 return minmax;
114
113 double[] minmax = new double[2]; 115 double[] minmax = new double[2];
114 minmax[0] = Double.MAX_VALUE; 116 minmax[0] = Double.MAX_VALUE;
115 minmax[1] = Double.MIN_VALUE; 117 minmax[1] = Double.MIN_VALUE;
116 118
117 int length = values.length; 119 int length = values.length;
118 for (int i = 0; i < length; i++) { 120 for (int i = 0; i < length; i++) {
119 minmax[0] = values[i] < minmax[0] ? values[i] : minmax[0]; 121 minmax[0] = values[i] < minmax[0] ? values[i] : minmax[0];
120 minmax[1] = values[i] > minmax[1] ? values[i] : minmax[1]; 122 minmax[1] = values[i] > minmax[1] ? values[i] : minmax[1];
121 } 123 }
122 124
125 this.minmax = minmax;
126
123 return minmax; 127 return minmax;
124 } 128 }
125 129
126 130
127 /** 131 /**
142 return values; 146 return values;
143 } 147 }
144 148
145 149
146 /** 150 /**
147 * Method to calculate the number of bins this chart should be parted into. 151 * Method to retrieve the number of bins.
148 * The real calculation takes place in {@link #getBinCountByNumber} and 152 *
149 * {@link #getBinCountByWidth}. This method switches between these methods 153 * @return the number of bins that is specified in <i>requestParameter</i>
150 * depending on the object stored in {@link #requestParameter}. 154 * or -1 if the number of bins is not the dominant value to calculate the
151 * 155 * width of a single bin.
152 * @param values All values used in this histogram 156 */
153 * 157 protected int getBinCount() {
154 * @return Number of bins 158 // Return -1 to trigger a calculation of the number of bins in
155 */ 159 // AdvancedHistogramDataset if the user chose the bin width as dominant
156 protected int getBinCount(double[] values) { 160 // value.
157 String param = (String) requestParameter.get(REQUEST_KEY_BIN_CHOICE); 161 String choice = (String) requestParameter.get(REQUEST_KEY_BIN_CHOICE);
158 162 if (choice != null && choice.equalsIgnoreCase(REQUEST_KEY_BIN_WIDTH)) {
159 if (param != null && param.equalsIgnoreCase(REQUEST_KEY_BIN_WIDTH)) { 163 return -1;
160 return getBinCountByWidth(values); 164 }
161 } 165
162 else {
163 return getBinCountByNumber();
164 }
165 }
166
167
168 /**
169 * Method to retrieve the number of bins. If {@link #requestParameter}
170 * contains a valid <code>Integer</code> at
171 * <code>REQUEST_KEY_BIN_COUNT</code> and this is smaller than or equal
172 * {@link #MAXIMAL_BINS}, this value is used. If no valid
173 * <code>Integer</code> is given or if the value in {@link #requestParameter}
174 * is bigger than {@link #MAXIMAL_BINS}, {@link #DEFAULT_BINS} is used.
175 *
176 * @return Number of bins
177 */
178 protected int getBinCountByNumber() {
179 int bins = -1; 166 int bins = -1;
180 String param = (String) requestParameter.get(REQUEST_KEY_BIN_COUNT); 167 String param = (String) requestParameter.get(REQUEST_KEY_BIN_COUNT);
181 168
182 try { 169 try {
183 bins = Integer.parseInt(param); 170 bins = Integer.parseInt(param);
194 } 181 }
195 } 182 }
196 183
197 184
198 /** 185 /**
199 * Serves the number of bins depending on a given width for each bin, but 186 * Serves width of a single bin.
200 * maximum bin count is limited by {@link #MAXIMAL_BINS}.
201 * 187 *
202 * @param values All values in this histogram 188 * @param values All values in this histogram
203 * 189 *
204 * @return Number of bins 190 * @return The bin width that is given in <i>requestParameter</i> or -1 if
205 */ 191 * the bin width is not the dominant value for calculating the number of
206 protected int getBinCountByWidth(double[] values) { 192 * bins in the histogram.
207 int bins = -1; 193 */
208 String param = (String) requestParameter.get(REQUEST_KEY_BIN_WIDTH); 194 protected double getBinWidth(double[] values) {
195 // Return -1 to trigger a calculation of the bin width in
196 // AdvancedHistogramDataset if the user chose the number of bins as
197 // dominant value.
198 String choice = (String) requestParameter.get(REQUEST_KEY_BIN_CHOICE);
199 if (choice == null || !choice.equalsIgnoreCase(REQUEST_KEY_BIN_WIDTH)) {
200 return -1;
201 }
202
203 int bins = -1;
204 String param = (String) requestParameter.get(REQUEST_KEY_BIN_WIDTH);
209 205
210 double[] minmax = getMinMax(values); 206 double[] minmax = getMinMax(values);
211 double totalWidth = minmax[1] - minmax[0]; 207 double totalWidth = minmax[1] - minmax[0];
212 double binWidth = Double.parseDouble(param); 208 double binWidth = Double.parseDouble(param);
213 209
214 double tmpBins = totalWidth / binWidth; 210 double tmpBins = totalWidth / binWidth;
215 211
216 bins = (int) Math.round(tmpBins); 212 bins = (int) Math.round(tmpBins);
217 bins = bins <= 0 ? DEFAULT_BINS : bins; 213 bins = bins <= 0 ? DEFAULT_BINS : bins;
218 bins = bins > MAXIMAL_BINS ? MAXIMAL_BINS : bins; 214
219 215 // the calculated number of bins with the given width exceed the maximum
220 return bins; 216 // number of bins.
217 if (bins > MAXIMAL_BINS) {
218 return totalWidth / (MAXIMAL_BINS);
219 }
220
221 return binWidth;
221 } 222 }
222 } 223 }
223 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : 224 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org