/* Monte-Carlo simulation code for statistical physics Copyright (C) 2001-2005 Sylvain Reynal Département de Physique Ecole Nationale Supérieure de l'Electronique et de ses Applications (ENSEA) 6, avenue du Ponceau, F-95014 CERGY CEDEX et Laboratoire de Physique Théorique et Modélisation (LPTM) Université de Cergy-Pontoise - Site de Neuville F-95031 CERGY CEDEX Tel : 00 +33 130 736 245 Fax : 00 +33 130 736 667 e-mail : reynal@ensea.fr web page : http://www.ensea.fr/staff/reynal/ */ package fr.ensea.montecarlo.data; import fr.ensea.chart.*; import JSci.awt.*; import java.awt.*; import java.text.*; import java.util.Locale; /** * A one-dimensional histogram with fixed bin width. * Plug on top of a Samples object to compute a histogram of its data. */ public class Histogram implements Curve2D { private Samples data; private int nbBins; private Point2D[] bins; // (bin-center, bin-height) for each bin private double minX, maxX, maxY, binWidth; // minY=0 /** * Construct an histogram of the given data, with nbBins bins */ protected Histogram(Samples data, int nbBins){ if (nbBins<2) throw new IllegalArgumentException("There must be more than one bin !"); this.nbBins = nbBins; this.data = data; update(); } /** * Recomputes all bin entries. Invokes when data have changed. */ protected synchronized void update(){ bins = new Point2D[nbBins]; binWidth = (data.getMax(Y_AXIS) - data.getMin(Y_AXIS))/(nbBins-1); minX = data.getMin(Y_AXIS) - binWidth/2.0; maxX = data.getMax(Y_AXIS) + binWidth/2.0; // create axis: double binCenter = data.getMin(Y_AXIS); for (int binIdx=0; binIdx < nbBins; binIdx++){ bins[binIdx] = new Point2D(binCenter,0); binCenter += binWidth; } // fill bins: for (int i=0; i maxY) maxY = entries; } } /** * To be invoked when a single sample has been added to the data since the last call to either * update() or updateIncremental(). * This may reduce overhead if "sample" lies within current histogram bounds. */ protected synchronized void updateIncremental(double sample){ if (sample < minX || sample > maxX) update(); else { int binIdx = coordToIndex(sample); bins[binIdx].y += 1.0; if (bins[binIdx].y > maxY) maxY = bins[binIdx].y; } } /** * Returns the number of bins */ public int bins(){ return nbBins; } /** * Returns the width of a bin */ public double binWidth(){ return binWidth; } /** * Returns the center of the ith bin */ public synchronized double binCenter(int i){ return bins[i].x; } /** * Returns the number of entries in the ith bin */ public synchronized double binEntries(int i){ return bins[i].y; } ////////////////////////////////////////////////////////// //// curve2D interface ////////////////////////////////////////////////////////// public synchronized Point2D getPoint(int i){ return bins[i]; } public int getNbPoints(){ return nbBins; } public double getMin(int axis){ switch (axis){ case X_AXIS: return minX; case Y_AXIS: return 0; default: throw new IllegalArgumentException("Wrong axis index : "+axis); } } public double getMax(int axis){ switch (axis){ case X_AXIS: return maxX; case Y_AXIS: return maxY; default: throw new IllegalArgumentException("Wrong axis index : "+axis); } } ////////////////////////////////////////////////////////// //// utilities ////////////////////////////////////////////////////////// // return the bin index to which the given value belongs private int coordToIndex(double val){ if (binWidth==0) return 0; int i = (int)Math.floor((val-minX)/binWidth); if (i>=nbBins) i = nbBins-1; if (i<0) i=0; return i; } ///////////////////////////////////////////////////////// //// test ///////////////////////////////////////////////////////// public String toString(){ NumberFormat nf = NumberFormat.getNumberInstance(Locale.US); nf.setMaximumFractionDigits(2); String s = "Histogram:\n"; s += "* nbBins="+nbBins+"\n"; s += "* binWidth="+binWidth+"\n"; s += "* x-axis=("+minX+","+maxX+")\n"; s += "* y-axis=(0,"+maxY+")\n"; s += "* center/height:\n"; for (int binIdx=0; binIdx < nbBins; binIdx++){ s += "[" + nf.format(bins[binIdx].x) + ", " + bins[binIdx].y + "] "; } return s; } public static void main(String[] args){ Frame frame = new Frame("test"); frame.setSize(400,400); Samples samples = new Samples(); for (int i = 0; i < 200; i++) samples.addSample(100.0 * Math.random() - 50.0); System.out.println(samples); Histogram histo = new Histogram(samples, 101); System.out.println(histo); Plot2D plot = new Plot2D(Color.black, Color.gray, Color.darkGray); plot.addCurve(histo,"N(E)",Color.green, DecoratedCurve2D.BARS_FILLED); plot.setTitle("Histogram"); plot.setXaxisLabel("E"); frame.add(plot); frame.show(); } }