package hep.aida.ref.histogram;

/**
 * Implementation of IHistogram1D.
 * @author The AIDA Team at SLAC.
 * @version $Id: Histogram1D.java 13479 2008-01-22 19:38:41Z serbo $
 *
 */

import hep.aida.IAxis;
import hep.aida.IHistogram1D;
import hep.aida.ref.event.IsObservable;
import hep.aida.ref.histogram.binner.AbstractBinner1D;
import hep.aida.ref.histogram.binner.BasicBinner1D;
import hep.aida.ref.histogram.binner.Binner1D;
import hep.aida.ref.histogram.binner.BinnerMath;
import hep.aida.ref.histogram.binner.EfficiencyBinner1D;
import java.util.Map;

public class Histogram1D extends Histogram implements IHistogram1D, IsObservable {
    
    /**
     * Create a 1-dimensional Histogram.
     *
     */
    public Histogram1D(){
        super("","",1, "");
    }
    
    /**
     * Create a 1-dimensional Histogram.
     * @param name The name of the Histogram as a ManagedObject.
     * @param title The title of the Histogram.
     * @param axis The x-axis of the Histogram.
     *
     */
    public Histogram1D(String name, String title, IAxis axis) {
        this(name,title,axis,"");
    }
    
    /**
     * Create a 1-dimensional Histogram.
     * @param name The name of the Histogram as a ManagedObject.
     * @param title The title of the Histogram.
     * @param axis The x-axis of the Histogram.
     * @param options options of the Histogram.
     *
     */
    protected Histogram1D(String name, String title, IAxis axis, String options) {
        super(name, title, 1, options);
        initHistogram1D(axis,options);
    }
    
    /**
     * Fill the Histogram with unit weight.
     * @param x The value to be filled.
     *
     */
    public void fill(double x) {
        fill(x,1.);
    }
    
    /**
     * Fill the Histogram.
     * @param x The value to be filled.
     * @param weight The weight for this entry.
     *
     */
    public void fill(double x, double weight) {
        if ( ! isFillable() ) throw new UnfillableHistogramException();
        allEntries++;
        if ( (! Double.isNaN(x)) && (!Double.isNaN(weight)) ) {
            int coordToIndex = xAxis.coordToIndex(x);
            int bin = mapBinNumber(coordToIndex, axis());
            /*
            double x0 = 0d;
            if ( coordToIndex == IAxis.UNDERFLOW_BIN ) {
                x0 = axis().lowerEdge();
            } else if ( coordToIndex == IAxis.OVERFLOW_BIN ) {
                x0 = axis().upperEdge();
            } else {
                x0 = axis().binCenter(coordToIndex);
            }
             */
            binner1D.fill(bin, x, weight);
            
            if ( coordToIndex >= 0 || useOutflows() ) {
                double delata = x - center;
                validEntries++;
                mean += delata*weight;
                rms  += delata*delata*weight;
                sumOfWeights += weight;
                sumOfWeightsSquared += weight*weight;
            }
        }
        
        if (isValid) fireStateChanged();
    }
    
    /**
     * Reset the Histogram. After calling this method the Histogram
     * is as it was just created.
     *
     */
    public void reset() {
        binner1D.clear();
        setBinCenters();
        mean = 0;
        rms  = 0;
        center = (xAxis.upperEdge() + xAxis.lowerEdge())/2;
        super.reset();
    }
    
    private void setBinCenters() {
        double x0 = 0;
        for (int i=0; i= -2; )
            sum += binHeight(i);
        return sum;
    }
    
    /**
     * Get the sum of the bin heights for all the entries outside the Histogram's range.
     * @return The sum of the out of range bin's heights.
     *
     */
    public double sumExtraBinHeights() {
        return binHeight(IAxis.UNDERFLOW_BIN) + binHeight(IAxis.OVERFLOW_BIN);
    }
    
    /**
     * Get the minimum height of in-range bins in the Histogram.
     * @return The minimum bin height for in range bins.
     *
     */
    public double minBinHeight() {
        double min=Double.NaN;
        for(int i=0; i= max) max=binHeight(i);
        return max;
    }
    
    /**
     * Number of entries in the corresponding bin (ie the number of times fill was called for this bin).
     * @param index the bin number in the external representation: (0...N-1) or OVERFLOW or UNDERFLOW.
     * @return The number of entries for the corresponding bin.
     *
     */
    public int binEntries(int index) {
        return binner1D.entries(mapBinNumber(index, axis()));
    }
    
    /**
     * Total height of the corresponding bin.
     * @param index The bin number in the external representation: (0...N-1) or OVERFLOW or UNDERFLOW.
     * @return The bin height for the corresponding bin.
     *
     */
    public double binHeight(int index) {
        return binner1D.height(mapBinNumber(index, axis()));
    }
    
    /**
     * The error on this bin.
     * @param index the bin number in the external representation: (0...N-1) or OVERFLOW or UNDERFLOW.
     * @return The error on the corresponding bin.
     *
     */
    public double binError(int index) {
        return binner1D.plusError(mapBinNumber(index, axis()));
    }
    
    
    /**
     * Get the mean of the whole Histogram. It includes all the entries (in and out of range).
     * @return The mean of the Histogram.
     *
     */
    public double mean() {
        if ( validEntries != 0 ) return mean/sumOfWeights + center;
        return 0;
    }
    
    /**
     * Get the RMS of the whole Histogram. It includes all the entries (in and out of range).
     * @return The RMS of the Histogram.
     *
     */
    public double rms(){
        if ( validEntries != 0 ) return Math.sqrt((rms - mean*mean/sumOfWeights)/sumOfWeights);
        return 0;
    }
    
    /**
     * Set the rms of the Histogram.
     * @param rms The Historam's x rms
     *
     */
    //public void setRms( double rms ) {
    //    this.rms = rms*rms*sumOfWeights + mean*mean*sumOfWeights;
    //}
    
    /**
     * Set the mean of the Histogram.
     * @param mean The Histogram's x mean
     *
     */
    public void setMeanAndRms( double otherMean, double otherRms ) {
        this.meanAndRmsIsSet = true;
        this.mean = (otherMean - center)*sumOfWeights;
        this.rms = otherRms*otherRms*sumOfWeights + (otherMean - center)*(otherMean - center)*sumOfWeights;
    }
    
    /**
     * Get the X axis.
     * @return The x axis.
     *
     */
    public IAxis axis() {
        return xAxis;
    }
    
    /**
     * Convenience method, equivalent to axis().coordToIndex(coord).
     * @see IAxis#coordToIndex(double)
     */
    public int coordToIndex(double coord) {
        return axis().coordToIndex(coord);
    }
    
    /**
     * Scale the weights and the errors by a given factor.
     *
     */
    public void scale(double scaleFactor) throws IllegalArgumentException {
        if ( scaleFactor <= 0 ) throw new IllegalArgumentException("Illegal scale factor "+scaleFactor+" it has to be positive");
        binner1D.scale(scaleFactor);
        mean *= scaleFactor;
        rms  *= scaleFactor;
        sumOfWeights *= scaleFactor;
        sumOfWeightsSquared *= scaleFactor*scaleFactor;
        if (isValid) fireStateChanged();
    }
    
    /**
     * Modifies this histogram by adding the contents of h to it.
     *
     * @param hist The histogram to be added to this histogram
     * @throws IllegalArgumentException if histogram binnings are incompatible
     */
    public void add(IHistogram1D hist) throws IllegalArgumentException {
        HistMath.checkCompatibility(axis(), hist.axis());
        int bins = axis().bins()+2;
        boolean h1Aida = !(hist instanceof Histogram1D);
        if (!h1Aida) {
            BinnerMath.add(binner1D, binner1D, ((Histogram1D) hist).binner());
            initHistogram1D(binner1D);
        } else {
            double[] newHeights = new double[bins];
            double[] newErrors  = new double[bins];
            double[] newMeans   = new double[bins];
            double[] newRmss    = new double[bins];
            int[]    newEntries = new int   [bins];
            double rms2 = 0;
            
            for(int i=IAxis.UNDERFLOW_BIN; i= 0 || useOutflows() && HistUtils.isValidDouble(h)) {
                if ( HistUtils.isValidDouble(m) ) {
                    double d = b2.binCenter(i) - center;
                    mean   += m + d*h;
                    rms    += r + d*(2*m + d*h);
                }
                validEntries += b2.entries(i);
                sumOfWeights += h;
                sumOfWeightsSquared += h*h;
            }
        }
    }
    void initHist1D( IAxis xAxis, String options ) {
        this.xAxis = xAxis;
        Map optionMap = hep.aida.ref.AidaUtils.parseOptions( options );
        String type = (String) optionMap.get("type");
        if ( type == null || type.equals("default") ) {
            binner1D = new BasicBinner1D(xAxis.bins()+2);
        } else if ( type.equals("efficiency") ) {
            binner1D = new EfficiencyBinner1D(xAxis.bins()+2);
        } else
            throw new IllegalArgumentException("Wrong histogram type "+type);
        
        String useOutflowsString = (String) optionMap.get("useOutflowsInStatistics");
        if ( useOutflowsString != null )
            setUseOutflows( Boolean.valueOf(useOutflowsString).booleanValue() );
        reset();
    }
    
    
    public AbstractBinner1D binner() {
        return binner1D;
    }
    
    private double mean = 0;
    private double rms = 0;
    private double center = 0;
    private IAxis xAxis;
    private AbstractBinner1D binner1D;
    
}

 

Ads help maintain this website.