View Javadoc

1   /*
2    * @(#) HistogramSeries.java Sep 22, 2003
3    * 
4    * Copyright (c) 2003 Delft University of Technology Jaffalaan 5, 2628 BX Delft,
5    * the Netherlands All rights reserved.
6    * 
7    * This software is proprietary information of Delft University of Technology
8    * The code is published under the General Public License
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 }