1
2
3
4
5
6
7
8
9
10 package nl.tudelft.simulation.jstats.charts.histogram;
11
12 import nl.tudelft.simulation.event.EventInterface;
13 import nl.tudelft.simulation.event.EventListenerInterface;
14
15 import org.jfree.data.AbstractDataset;
16
17
18 /***
19 * The serie defines a histogram series containing the entries of a set.
20 * <p>
21 * (c) copyright 2002-2004 <a href="http://www.simulation.tudelft.nl">Delft
22 * University of Technology </a>, the Netherlands. <br>
23 * See for project information <a href="http://www.simulation.tudelft.nl">
24 * www.simulation.tudelft.nl </a> <br>
25 * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General Public
26 * License (GPL) </a>, no warranty <br>
27 *
28 * @author <a href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">
29 * Alexander Verbraeck </a> <br>
30 * <a href="http://www.tbm.tudelft.nl/webstaf/peterja/index.htm"> Peter
31 * Jacobs </a>
32 * @version 1.7 2004-03-22
33 * @since 1.2
34 */
35 public class HistogramSeries extends AbstractDataset implements
36 EventListenerInterface
37 {
38
39 /***
40 * name refers to the name of the serie
41 *
42 * @uml.property name="name"
43 */
44 private String name;
45
46
47 /*** bins refers to the bins in this serie */
48 private Bin[] bins = null;
49
50 /***
51 * constructs a new HistogramSeries
52 *
53 * @param name the name of the dataset
54 * @param domain the domain of the serie
55 * @param range the range of the serie
56 * @param numberOfBins the number of bins to be used
57 */
58 public HistogramSeries(final String name, final double[] domain,
59 final double[] range, final int numberOfBins)
60 {
61
62 super();
63 this.name = name;
64 this.bins = new Bin[numberOfBins + 2];
65 double binWidth = (domain[1] - domain[0]) / numberOfBins * 1.0;
66 double min = domain[0] - binWidth;
67 for (int i = 0; i < numberOfBins + 2; i++)
68 {
69 this.bins[i] = new Bin(new double[]{min, min + binWidth}, range);
70 if (range != null)
71 {
72 this.bins[i].setFixed(true);
73 }
74 min = min + binWidth;
75 }
76 this.fireDatasetChanged();
77 }
78
79 /***
80 * returns the name of the serie
81 *
82 * @return String the name
83 *
84 * @uml.property name="name"
85 */
86 public String getName()
87 {
88 return this.name;
89 }
90
91 /***
92 * returns the maxX value for bin
93 *
94 * @param bin the bin number
95 * @return Number
96 */
97 public Number getEndXValue(final int bin)
98 {
99 return this.bins[bin].getEndXValue();
100 }
101
102 /***
103 * returns the maxY value
104 *
105 * @param bin the bin number
106 * @return Number
107 */
108 public Number getEndYValue(final int bin)
109 {
110 return this.bins[bin].getEndYValue();
111 }
112
113 /***
114 * returns the minimumX value
115 *
116 * @param bin the bin number
117 * @return Number
118 */
119 public Number getStartXValue(final int bin)
120 {
121 return this.bins[bin].getStartXValue();
122 }
123
124 /***
125 * returns the minimumY value
126 *
127 * @param bin the bin number
128 * @return Number
129 */
130 public Number getStartYValue(final int bin)
131 {
132 return this.bins[bin].getStartYValue();
133 }
134
135 /***
136 * returns the number of bins in the histogram
137 *
138 * @return int
139 */
140 public int getBinCount()
141 {
142 return this.bins.length;
143 }
144
145 /***
146 * returns the x value
147 *
148 * @param bin the bin number
149 * @return Number
150 */
151 public Number getXValue(final int bin)
152 {
153 return this.bins[bin].getXValue();
154 }
155
156 /***
157 * returns the Y value
158 *
159 * @param bin the bin number
160 * @return Number
161 */
162 public Number getYValue(final int bin)
163 {
164 return this.bins[bin].getYValue();
165 }
166
167 /***
168 * @see nl.tudelft.simulation.event.EventListenerInterface
169 * #notify(nl.tudelft.simulation.event.EventInterface)
170 */
171 public synchronized void notify(final EventInterface event)
172 {
173 double value = ((Number) event.getContent()).doubleValue();
174 this.bins[this.resolveBin(value)].increase();
175 this.fireDatasetChanged();
176 }
177
178 /***
179 * resolves the bin for a particular value
180 *
181 * @param value the value of the incomming event
182 * @return int the bin number
183 */
184 private int resolveBin(final double value)
185 {
186 if (value <= this.bins[1].getStartXValue().doubleValue())
187 {
188 return 0;
189 }
190 for (int i = 1; i < this.bins.length - 1; i++)
191 {
192 if (value > this.bins[i].getStartXValue().doubleValue()
193 && value <= this.bins[i].getEndXValue().doubleValue())
194 {
195 return i;
196 }
197 }
198 return this.bins.length - 1;
199 }
200
201 /***
202 * defines the bins in the histogram.
203 */
204 private class Bin
205 {
206 /*** the domain of the bin */
207 private double[] domain;
208
209 /*** the range of the bin */
210 private double[] range = null;
211
212 /*** observations refers to the value of this bin */
213 private int observations = 0;
214
215 /*** fixed refers to autoscaling versus fixed scaling */
216 private boolean fixed = false;
217
218 /***
219 * constructs a new Bin
220 *
221 * @param domain the domain of the bin
222 * @param range the range of the bin
223 */
224 public Bin(final double[] domain, final double[] range)
225 {
226 this.domain = domain;
227 if (range == null)
228 {
229 this.range = new double[]{0, 1};
230 } else
231 {
232 this.range = range;
233 this.fixed = true;
234 }
235 }
236
237 /***
238 * increases the value of the bin with 1
239 */
240 public void increase()
241 {
242 this.observations++;
243 if (!this.fixed && this.observations >= this.range[1])
244 {
245 this.range[1] = this.observations;
246 }
247 }
248
249 /***
250 * returns the minimum x value
251 *
252 * @return Number
253 */
254 public Number getStartXValue()
255 {
256 return new Double(this.domain[0]);
257 }
258
259 /***
260 * returns the minimum y value
261 *
262 * @return Number
263 */
264 public Number getStartYValue()
265 {
266 return new Double(this.range[0]);
267 }
268
269 /***
270 * returns the maximum X value
271 *
272 * @return Number
273 */
274 public Number getEndXValue()
275 {
276 return new Double(this.domain[1]);
277 }
278
279 /***
280 * returns the maximum Y value
281 *
282 * @return Number
283 */
284 public Number getEndYValue()
285 {
286 return new Double(this.range[1]);
287 }
288
289 /***
290 * returns the x value
291 *
292 * @return Number
293 */
294 public synchronized Number getXValue()
295 {
296 return new Double(0.5 * (this.domain[1] - this.domain[0]));
297 }
298
299 /***
300 * returns the y value
301 *
302 * @return Number
303 */
304 public Number getYValue()
305 {
306 return new Integer(this.observations);
307 }
308
309 /***
310 * sets the fixed attributed
311 *
312 * @param fixed is the bin fixed in range
313 */
314 public void setFixed(final boolean fixed)
315 {
316 this.fixed = fixed;
317 }
318 }
319 }