package hep.aida.ref.dataset.binner;
import hep.aida.ref.dataset.DataStatistics;
/**
* The default implementation of a Binner.
*
* @author The FreeHEP team at SLAC
*
*/
public class DefaultBinner implements Binner {
private int[] maxBins;
private int nBins = 1;
private int dimension;
private DataStatistics[] binStats;
private BinError binError;
/**
* Creates a new instance of Binner.
* @param bins The array containing the number of bins per coordinate.
* @param options The options.
*
*/
public DefaultBinner(int[] bins, String options) {
this.dimension = bins.length;
maxBins = new int[dimension];
for ( int j = 0; j < dimension; j++ )
maxBins[j] = bins[j];
for ( int i = 0; i < dimension; i++ ) {
if (bins[i] < 0) throw new IllegalArgumentException("Number of bins cannot be negative!!! "+bins);
nBins *= bins[i];
}
setBinError( new GaussianBinError() );
binStats = new DataStatistics[ nBins ];
for ( int i = 0; i < nBins; i++ )
binStats[i] = new DataStatistics(dimension);
}
/**
* Utility method to convert from the bin numbering to the
* internal bin representation.
* For a bin represented by int[] {binx, biny, binz} we use
* the internal numbering: binx + biny*nBinsx + binz*nBinsx*nBinsy
*
*/
protected int internalBin(int[] bin) {
checkDimension(bin);
int ibin = 0;
int b = 1;
for ( int i = 0; i < dimension; i++ ) {
ibin += bin[i]*b;
b *= maxBins[i];
}
return ibin;
}
/**
* Utility method to check the dimension of the bin.
*
*/
private void checkDimension( int[] bin ) {
if ( bin.length != dimension )
throw new IllegalArgumentException("Illegal dimension "+bin.length+". It must be "+dimension);
}
/**
* Utility method to access a bin's statistical information.
*
*/
protected DataStatistics binStatistics( int bin ) {
return binStats[ bin ];
}
/**
* Fill a bin with a new entry.
* @param bin The array specifying the bin.
* @param x The coordinate's array
* @param weight The weight for this entry.
*
*/
public void fill( int[] bin, double[] x, double weight) {
int iBin = internalBin( bin );
binStatistics( iBin ).addEntry( x, weight );
}
/**
* Set at once the content of a bin.
* @param bin The array specifying the bin.
* @param entries The entries in the bin.
* @param height The height of the bin.
* @param mean The array with the coordinate means
* @param rms The array with the coordinate rmss
*
*/
public void setBinContent(int[] bin, int entries, double height, double[] mean, double[] rms) {
int iBin = internalBin( bin );
resetBin( iBin );
binStatistics( iBin ).addEntries( mean, rms, height, 0, entries );
}
public void addContentToBin(int[] bin, int entries, double height, double[] mean, double[] rms) {
int iBin = internalBin( bin );
binStatistics( iBin ).addEntries( mean, rms, height, 0, entries );
}
public void removeContentFromBin(int[] bin, int entries, double height, double[] mean, double[] rms) {
int iBin = internalBin( bin );
binStatistics( iBin ).removeEntries( mean, rms, height, 0, entries );
}
/**
* Reset the content of a bin.
* @param bin The array specifying the bin.
*
*/
public void resetBin(int[] bin) {
int iBin = internalBin( bin );
resetBin( iBin );
}
/**
* Reset the content of the Binner.
*
*/
public void reset() {
for ( int i = 0; i < nBins; i++ )
resetBin(i);
}
/**
* Reset the content of a bin.
* @param bin The bin number in the internal representation.
*
*/
private void resetBin( int bin ) {
binStatistics( bin ).reset();
}
/**
* Get the number of entries in a bin.
* @param bin The array specifying the bin.
*
*/
public int entries(int[] bin) {
int iBin = internalBin( bin );
return binStatistics( iBin ).entries();
}
/**
* Get the height of a bin.
* @param bin The array specifying the bin.
*
*/
public double height(int[] bin) {
int iBin = internalBin( bin );
return binStatistics( iBin ).sumOfWeights();
}
/**
* Get the plus error on a bin.
* @param bin The array specifying the bin.
*
*/
public double plusError(int[] bin) {
int iBin = internalBin( bin );
return binError.plusError(binStatistics( iBin ).entries(), binStatistics( iBin ).sumOfWeights() );
}
/**
* Get the minus error on a bin.
* @param bin The array specifying the bin.
*
*/
public double minusError(int[] bin) {
int iBin = internalBin( bin );
return binError.minusError(binStatistics( iBin ).entries(), binStatistics( iBin ).sumOfWeights() );
}
/**
* Get the mean of a bin along a given coordinate.
* @param bin The array specifying the bin.
* @param coord The coordinate's index.
*
*/
public double mean(int[] bin, int coord) {
int iBin = internalBin( bin );
return binStatistics( iBin ).mean(coord);
}
/**
* Get the rms of a bin along a given coordinate.
* @param bin The array specifying the bin.
* @param coord The coordinate's index.
*
*/
public double rms(int[] bin, int coord) {
int iBin = internalBin( bin );
return binStatistics( iBin ).rms(coord);
}
/**
* Scale all the bins by a given scale factor.
* @param scaleFactor The scale factor.
*
*/
public void scale(double scaleFactor) {
for ( int i = 0; i < nBins; i++ )
binStatistics( i ).scale(scaleFactor);
}
/**
* Set the BinError with which the plus and minus
* error on the bin are calculated.
* @param binError The BinError.
*
*
*/
public void setBinError(BinError binError) {
this.binError = binError;
}
}