Mercurial > dive4elements > gnv-client
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 : |