package hep.aida.ref.histogram;
import hep.aida.IAxis;
/**
* Fixed-width axis; A reference implementation of hep.aida.IAxis.
*
* @author The AIDA team @ SLAC.
* @version $Id: FixedAxis.java 8584 2006-08-10 23:06:37Z duns $
*/
public class FixedAxis implements IAxis {
private int bins;
private double min;
private double binWidth;
private int xunder, xover;
private double max;
/**
* Create an Axis
* @param bins Number of bins
* @param min Minimum for axis
* @param max Maximum for axis
*/
public FixedAxis(int bins, double min, double max) {
if (bins < 1) throw new IllegalArgumentException("bins="+bins);
if (max <= min) throw new IllegalArgumentException("max <= min");
// Note, for internal consistency we save only min and binWidth
// and always use these quantities for all calculations. Due to
// rounding errors the return value from upperEdge is not necessarily
// exactly equal to max
this.bins = bins;
this.min = min;
this.binWidth = (max - min)/bins;
this.max = max;
// our internal definition of overflow/underflow differs from
// that of the outside world
this.xunder = 0;
this.xover = bins+1;
}
/**
* Check if two Axis are equal.
* @param o the Object to check
* @return <code>true</code> if <code>o</code> is an instance of FixedAxis and
* it has the same number of bins, minimum and bin width.
*/
public boolean equals(Object o) {
if (o instanceof FixedAxis) {
FixedAxis other = (FixedAxis) o;
return this.bins == other.bins && this.min == other.min && this.binWidth == other.binWidth;
}
return false;
}
public double binCenter(int index) {
if ( index == IAxis.OVERFLOW_BIN )
return Double.POSITIVE_INFINITY;
if ( index == IAxis.UNDERFLOW_BIN )
return Double.NEGATIVE_INFINITY;
return min + binWidth*index + binWidth/2;
}
/**
* Get the number of bins in the Axis.
* @return the number of bins.
*/
public int bins() {
return bins;
}
/**
* Get the lower edge of a bin.
* @param index the bin's index
* @return the bin's lower edge. If <code>index</code> corresponds
* to the UNDERFLOW_BIN, Double.NEGATIVE_INFINITY is returned.
* If <code>index</code> corresponds to OVERFLOW_BIN, the
* upper edge of the axis is returned.
*/
public double binLowerEdge(int index) {
if (index == IAxis.UNDERFLOW_BIN) return Double.NEGATIVE_INFINITY;
if (index == IAxis.OVERFLOW_BIN) return upperEdge();
if ( Double.isInfinite(min) )
return min;
return min + binWidth*index;
}
/**
* Get the upper edge of a bin.
* @param index the bin's index
* @return the bin's upper edge. If <code>index</code> corresponds
* to the OVERFLOW_BIN, Double.POSITIVE_INFINITY is returned.
* If <code>index</code> corresponds to UNDERFLOW_BIN, the
* lower edge of the axis is returned.
*/
public double binUpperEdge(int index) {
if (index == IAxis.UNDERFLOW_BIN) return min;
if (index == IAxis.OVERFLOW_BIN) return Double.POSITIVE_INFINITY;
if ( Double.isInfinite(min) )
return min;
return min + binWidth*(index+1);
}
/**
* Get the bin width.
* @param index the bin's index. For a Fixed Axis the bin's width is constant.
* @return the bin's width.
**/
public double binWidth(int index) {
if (index == IAxis.UNDERFLOW_BIN) return Double.POSITIVE_INFINITY;
if (index == IAxis.OVERFLOW_BIN) return Double.POSITIVE_INFINITY;
return binWidth;
}
/**
* Get the bin's index corresponding to an axis's value.
* @param coord an axis value
* @return the bin's index corresponding to <code>coord</code>
*/
public int coordToIndex(double coord) {
if (coord < min) return IAxis.UNDERFLOW_BIN;
int index = (int) Math.floor((coord - min)/binWidth);
if (index >= bins) return IAxis.OVERFLOW_BIN;
return index;
}
/**
* Get the Axis lower edge.
* @return the axis lower edge
*/
public double lowerEdge() {
return min;
}
/**
* Get the Axis upper edge.
* @return the axis upper edge
*/
public double upperEdge() {
if ( Double.isInfinite(max) )
return max;
return min + binWidth*bins;
}
/**
* This package private method is similar to coordToIndex except
* that it returns our internal definition for overflow/underflow
*/
int xgetBin(double coord) {
if (coord < min) return xunder;
int index = (int) Math.floor((coord - min)/binWidth);
if (index > bins) return xover;
return index+1;
}
/**
* Package private method to map from the external representation of bin
* number to our internal representation of bin number
*/
int xmap(int index) {
if (index >= bins) throw new IllegalArgumentException("bin="+index);
if (index >= 0) return index+1;
if (index == IAxis.UNDERFLOW_BIN) return xunder;
if (index == IAxis.OVERFLOW_BIN) return xover;
throw new IllegalArgumentException("bin="+index);
}
public boolean isFixedBinning() {
return true;
}
}