1 59 60 package org.jfree.data.statistics; 61 62 import java.io.Serializable ; 63 import java.util.ArrayList ; 64 import java.util.HashMap ; 65 import java.util.List ; 66 import java.util.Map ; 67 68 import org.jfree.data.general.DatasetChangeEvent; 69 import org.jfree.data.xy.AbstractIntervalXYDataset; 70 import org.jfree.data.xy.IntervalXYDataset; 71 import org.jfree.util.ObjectUtilities; 72 import org.jfree.util.PublicCloneable; 73 74 79 public class HistogramDataset extends AbstractIntervalXYDataset 80 implements IntervalXYDataset, 81 Cloneable , PublicCloneable, 82 Serializable { 83 84 85 private static final long serialVersionUID = -6341668077370231153L; 86 87 88 private List list; 89 90 91 private HistogramType type; 92 93 97 public HistogramDataset() { 98 this.list = new ArrayList (); 99 this.type = HistogramType.FREQUENCY; 100 } 101 102 107 public HistogramType getType() { 108 return this.type; 109 } 110 111 117 public void setType(HistogramType type) { 118 if (type == null) { 119 throw new IllegalArgumentException ("Null 'type' argument"); 120 } 121 this.type = type; 122 notifyListeners(new DatasetChangeEvent(this, this)); 123 } 124 125 132 public void addSeries(Comparable key, double[] values, int bins) { 133 double minimum = getMinimum(values); 135 double maximum = getMaximum(values); 136 addSeries(key, values, bins, minimum, maximum); 137 } 138 139 151 public void addSeries(Comparable key, 152 double[] values, 153 int bins, 154 double minimum, 155 double maximum) { 156 157 if (key == null) { 158 throw new IllegalArgumentException ("Null 'key' argument."); 159 } 160 if (values == null) { 161 throw new IllegalArgumentException ("Null 'values' argument."); 162 } 163 else if (bins < 1) { 164 throw new IllegalArgumentException ( 165 "The 'bins' value must be at least 1."); 166 } 167 double binWidth = (maximum - minimum) / bins; 168 169 double lower = minimum; 170 double upper; 171 List binList = new ArrayList (bins); 172 for (int i = 0; i < bins; i++) { 173 HistogramBin bin; 174 if (i == bins - 1) { 178 bin = new HistogramBin(lower, maximum); 179 } 180 else { 181 upper = minimum + (i + 1) * binWidth; 182 bin = new HistogramBin(lower, upper); 183 lower = upper; 184 } 185 binList.add(bin); 186 } 187 for (int i = 0; i < values.length; i++) { 189 int binIndex = bins - 1; 190 if (values[i] < maximum) { 191 double fraction = (values[i] - minimum) / (maximum - minimum); 192 if (fraction < 0.0) { 193 fraction = 0.0; 194 } 195 binIndex = (int) (fraction * bins); 196 if (binIndex >= bins) { 200 binIndex = bins - 1; 201 } 202 } 203 HistogramBin bin = (HistogramBin) binList.get(binIndex); 204 bin.incrementCount(); 205 } 206 Map map = new HashMap (); 208 map.put("key", key); 209 map.put("bins", binList); 210 map.put("values.length", new Integer (values.length)); 211 map.put("bin width", new Double (binWidth)); 212 this.list.add(map); 213 } 214 215 223 private double getMinimum(double[] values) { 224 if (values == null || values.length < 1) { 225 throw new IllegalArgumentException ( 226 "Null or zero length 'values' argument."); 227 } 228 double min = Double.MAX_VALUE; 229 for (int i = 0; i < values.length; i++) { 230 if (values[i] < min) { 231 min = values[i]; 232 } 233 } 234 return min; 235 } 236 237 245 private double getMaximum(double[] values) { 246 if (values == null || values.length < 1) { 247 throw new IllegalArgumentException ( 248 "Null or zero length 'values' argument."); 249 } 250 double max = -Double.MAX_VALUE; 251 for (int i = 0; i < values.length; i++) { 252 if (values[i] > max) { 253 max = values[i]; 254 } 255 } 256 return max; 257 } 258 259 270 List getBins(int series) { 271 Map map = (Map ) this.list.get(series); 272 return (List ) map.get("bins"); 273 } 274 275 282 private int getTotal(int series) { 283 Map map = (Map ) this.list.get(series); 284 return ((Integer ) map.get("values.length")).intValue(); 285 } 286 287 294 private double getBinWidth(int series) { 295 Map map = (Map ) this.list.get(series); 296 return ((Double ) map.get("bin width")).doubleValue(); 297 } 298 299 304 public int getSeriesCount() { 305 return this.list.size(); 306 } 307 308 319 public Comparable getSeriesKey(int series) { 320 Map map = (Map ) this.list.get(series); 321 return (Comparable ) map.get("key"); 322 } 323 324 335 public int getItemCount(int series) { 336 return getBins(series).size(); 337 } 338 339 354 public Number getX(int series, int item) { 355 List bins = getBins(series); 356 HistogramBin bin = (HistogramBin) bins.get(item); 357 double x = (bin.getStartBoundary() + bin.getEndBoundary()) / 2.; 358 return new Double (x); 359 } 360 361 374 public Number getY(int series, int item) { 375 List bins = getBins(series); 376 HistogramBin bin = (HistogramBin) bins.get(item); 377 double total = getTotal(series); 378 double binWidth = getBinWidth(series); 379 380 if (this.type == HistogramType.FREQUENCY) { 381 return new Double (bin.getCount()); 382 } 383 else if (this.type == HistogramType.RELATIVE_FREQUENCY) { 384 return new Double (bin.getCount() / total); 385 } 386 else if (this.type == HistogramType.SCALE_AREA_TO_1) { 387 return new Double (bin.getCount() / (binWidth * total)); 388 } 389 else { throw new IllegalStateException (); 391 } 392 } 393 394 406 public Number getStartX(int series, int item) { 407 List bins = getBins(series); 408 HistogramBin bin = (HistogramBin) bins.get(item); 409 return new Double (bin.getStartBoundary()); 410 } 411 412 424 public Number getEndX(int series, int item) { 425 List bins = getBins(series); 426 HistogramBin bin = (HistogramBin) bins.get(item); 427 return new Double (bin.getEndBoundary()); 428 } 429 430 444 public Number getStartY(int series, int item) { 445 return getY(series, item); 446 } 447 448 462 public Number getEndY(int series, int item) { 463 return getY(series, item); 464 } 465 466 473 public boolean equals(Object obj) { 474 if (obj == this) { 475 return true; 476 } 477 if (!(obj instanceof HistogramDataset)) { 478 return false; 479 } 480 HistogramDataset that = (HistogramDataset) obj; 481 if (!ObjectUtilities.equal(this.type, that.type)) { 482 return false; 483 } 484 if (!ObjectUtilities.equal(this.list, that.list)) { 485 return false; 486 } 487 return true; 488 } 489 490 497 public Object clone() throws CloneNotSupportedException { 498 return super.clone(); 499 } 500 501 } 502 | Popular Tags |