package hep.aida.ref.histogram;
import hep.aida.IAxis;
import java.io.*;

/**
 * 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, Serializable {
    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 true if o 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 index corresponds
     *         to the UNDERFLOW_BIN, Double.NEGATIVE_INFINITY is returned.
     *         If index 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 index corresponds
     *         to the OVERFLOW_BIN, Double.POSITIVE_INFINITY is returned.
     *         If index 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 coord
     */
    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;
    }
}

 

Ads help maintain this website.