package hep.aida.ref;
import hep.aida.IAxis;
import hep.aida.IHistogram1D;
/**
A reference implementation of hep.aida.IHistogram1D.
The goal is to provide a clear implementation rather than the most efficient implementation.
However, performance seems fine - filling 1.2 * 10^6 points/sec, both using FixedAxis or VariableAxis.
@author Wolfgang Hoschek, Tony Johnson, and others.
@version 1.0, 23/03/2000
*/
public class Histogram1D extends AbstractHistogram1D implements IHistogram1D
{
private double[] errors;
private double[] heights;
private int[] entries;
private int nEntry; // total number of times fill called
private double sumWeight; // Sum of all weights
private double sumWeightSquared; // Sum of the squares of the weights
private double mean, rms;
/**
* Creates a variable-width histogram.
* Example: <tt>edges = (0.2, 1.0, 5.0)</tt> yields an axis with 2 in-range bins <tt>[0.2,1.0), [1.0,5.0)</tt> and 2 extra bins <tt>[-inf,0.2), [5.0,inf]</tt>.
* @param title The histogram title.
* @param edges the bin boundaries the axis shall have;
* must be sorted ascending and must not contain multiple identical elements.
* @throws IllegalArgumentException if <tt>edges.length < 1</tt>.
*/
public Histogram1D(String title, double[] edges)
{
this(title,new VariableAxis(edges));
}
/**
* Creates a fixed-width histogram.
*
* @param title The histogram title.
* @param bins The number of bins.
* @param min The minimum value on the X axis.
* @param max The maximum value on the X axis.
*/
public Histogram1D(String title, int bins, double min, double max)
{
this(title,new FixedAxis(bins,min,max));
}
/**
* Creates a histogram with the given axis binning.
*
* @param title The histogram title.
* @param axis The axis description to be used for binning.
*/
public Histogram1D(String title, IAxis axis)
{
super(title);
xAxis = axis;
int bins = axis.bins();
entries = new int[bins+2];
heights = new double[bins+2];
errors = new double[bins+2];
}
public int allEntries() // perhaps to be deleted (default impl. in superclass sufficient)
{
return nEntry;
}
public int binEntries(int index)
{
//return entries[xAxis.map(index)];
return entries[map(index)];
}
public double binError(int index)
{
//return Math.sqrt(errors[xAxis.map(index)]);
return Math.sqrt(errors[map(index)]);
}
public double binHeight(int index)
{
//return heights[xAxis.map(index)];
return heights[map(index)];
}
public double equivalentBinEntries()
{
return sumWeight*sumWeight/sumWeightSquared;
}
public void fill(double x)
{
//int bin = xAxis.getBin(x);
int bin = map(xAxis.coordToIndex(x));
entries[bin]++;
heights[bin]++;
errors[bin]++;
nEntry++;
sumWeight++;
sumWeightSquared++;
mean += x;
rms += x*x;
}
public void fill(double x, double weight)
{
//int bin = xAxis.getBin(x);
int bin = map(xAxis.coordToIndex(x));
entries[bin]++;
heights[bin] += weight;
errors[bin] += weight*weight;
nEntry++;
sumWeight += weight;
sumWeightSquared += weight*weight;
mean += x*weight;
rms += x*weight*weight;
}
public double mean()
{
return mean/sumWeight;
}
public void reset()
{
for (int i=0; i<entries.length; i++)
{
entries[i] = 0;
heights[i] = 0;
errors[i] = 0;
}
nEntry = 0;
sumWeight = 0;
sumWeightSquared = 0;
mean = 0;
rms = 0;
}
public double rms()
{
return Math.sqrt(rms/sumWeight - mean*mean/sumWeight/sumWeight);
}
/**
* Used internally for creating slices and projections
*/
void setContents(int[] entries, double[] heights, double[] errors)
{
this.entries = entries;
this.heights = heights;
this.errors = errors;
for (int i=0; i<entries.length; i++)
{
nEntry += entries[i];
sumWeight += heights[i];
}
// TODO: Can we do anything sensible/useful with the other statistics?
sumWeightSquared = Double.NaN;
mean = Double.NaN;
rms = Double.NaN;
}
}