package hep.aida.ref.histogram;

/**
 * Implementation of IHistogram3D.
 * @author The AIDA Team at SLAC.
 * @version $Id: Histogram3D.java 9095 2006-10-06 17:53:30Z serbo $
 *
 */

import hep.aida.IAxis;
import hep.aida.IHistogram3D;
import hep.aida.ref.histogram.binner.BasicBinner3D;
import hep.aida.ref.histogram.binner.Binner3D;
import hep.aida.ref.histogram.binner.EfficiencyBinner3D;
import java.io.Serializable;

import java.util.Map;

public class Histogram3D extends Histogram implements IHistogram3D, Serializable {
    
    /**
     * Create a 3-dimensional Histogram.
     */
    public Histogram3D(){
        super("","",3, "");
    }
    
    /**
     * Create a 3-dimensional Histogram.
     * @param name The name of the Histogram as a ManagedObject.
     * @param title The title of the Histogram.
     * @param xAxis The x-axis of the Histogram.
     * @param yAxis The y-axis of the Histogram.
     * @param zAxis The z-axis of the Histogram.
     *
     */
    public  Histogram3D(String name, String title, IAxis xAxis, IAxis yAxis, IAxis zAxis) {
        this(name,title,xAxis,yAxis,zAxis,"");
    }
    
    /**
     * Create a 3-dimensional Histogram.
     * @param name The name of the Histogram as a ManagedObject.
     * @param title The title of the Histogram.
     * @param xAxis The x-axis of the Histogram.
     * @param yAxis The y-axis of the Histogram.
     * @param zAxis The z-axis of the Histogram.
     * @param options The options of the Histogram.
     *
     */
    public  Histogram3D(String name, String title, IAxis xAxis, IAxis yAxis, IAxis zAxis, String options) {
        super(name, title, 3, options);
        initHistogram3D(xAxis,yAxis,zAxis,options);
    }
    
    /**
     * Fill the Histogram with unit weight.
     * @param x The x value to be filled.
     * @param y The y value to be filled.
     * @param z The z value to be filled.
     *
     */
    public void fill(double x, double y, double z) {
        fill(x, y, z, 1.);
    }
    
    /**
     * Fill the Histogram.
     * @param x The x value to be filled.
     * @param y The y value to be filled.
     * @param z The z value to be filled.
     * @param weight The weight for this entry.
     *
     */
    public void fill( double x, double y, double z, double weight) {
        if ( ! isFillable() ) throw new UnfillableHistogramException();
        allEntries++;
        
        if ( (! Double.isNaN(x)) && (!Double.isNaN(y)) && (!Double.isNaN(z)) && (!Double.isNaN(weight))) {
            int xCoordToIndex = xAxis.coordToIndex(x);
            int yCoordToIndex = yAxis.coordToIndex(y);
            int zCoordToIndex = zAxis.coordToIndex(z);
            int xBin = mapBinNumber(xCoordToIndex, xAxis());
            int yBin = mapBinNumber(yCoordToIndex, yAxis());
            int zBin = mapBinNumber(zCoordToIndex, zAxis());
            binner3D.fill(xBin,yBin,zBin,x,y,z,weight);
            
            if ( ( xCoordToIndex >= 0 && yCoordToIndex >= 0 && zCoordToIndex >= 0) || useOutflows() ) {
                validEntries++;
                meanX += x*weight;
                rmsX += x*x*weight;
                meanY += y*weight;
                rmsY += y*y*weight;
                meanZ += z*weight;
                rmsZ += z*z*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() {
        binner3D.clear();
        meanX = 0;
        rmsX = 0;
        meanY = 0;
        rmsY = 0;
        meanZ = 0;
        rmsZ = 0;
        super.reset();
    }
    
    /**
     * Get the number of entries in the underflow and overflow bins.
     * @return The number of entries outside the range of the Histogram.
     *
     */
    public int extraEntries() {
        int n = 0;
        for (int i=xAxis.bins(); --i >= -2;)
            for (int j=yAxis.bins(); --j >= -2;)
                for (int k=zAxis.bins(); --k >= -2;) {
            if ( i<0 || j<0 || k<0 ) n += binEntries(i,j,k);
                }
        return n;
    }
    
    /**
     * Get the sum of the bin heights for all the entries, in-range and out-range ones.
     * @return The sum of all the bin's heights.
     *
     */
    public double sumAllBinHeights() {
        double sum = 0;
        for (int i=xAxis.bins(); --i >= -2;)
            for (int j=yAxis.bins(); --j >= -2;)
                for (int k=zAxis.bins(); --k >= -2;)
                    sum += binHeight(i,j,k);
        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() {
        int sum = 0;
        for (int i=xAxis.bins(); --i >= -2;)
            for (int j=yAxis.bins(); --j >= -2;)
                for (int k=zAxis.bins(); --k >= -2;)
                    if ( i<0 || j<0 || k<0 ) sum += binHeight(i,j,k);
        return sum;
    }
    
    /**
     * 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=1; i<=xAxis.bins(); i++)
            for(int j=1; j<=yAxis.bins(); j++)
                for(int k=1; k<=zAxis.bins(); k++)
                    if(Double.isNaN(min) || binHeight(i,j,k) <= min) min=binHeight(i,j,k);
        return min;
    }
    
    /**
     * Get the maximum height of in-range bins in the Histogram.
     * @return The maximum bin height for in range bins.
     *
     */
    public double maxBinHeight() {
        double max=Double.NaN;
        for(int i=1; i<=xAxis.bins(); i++)
            for(int j=1; j<=yAxis.bins(); j++)
                for(int k=1; k<=zAxis.bins(); k++)
                    if(Double.isNaN(max) || binHeight(i,j,k) >= max) max=binHeight(i,j,k);
        return max;
    }
    
    /**
     * Number of entries in the corresponding bin (ie the number of times fill was called for this bin).
     * @param indexX The x bin number in the external representation: (0...N-1) or OVERFLOW or UNDERFLOW.
     * @param indexY The y bin number in the external representation: (0...N-1) or OVERFLOW or UNDERFLOW.
     * @param indexZ The z 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 indexX, int indexY, int indexZ) {
        return binner3D.entries(mapBinNumber(indexX, xAxis()),mapBinNumber(indexY, yAxis()),mapBinNumber(indexZ,zAxis()));
    }
    
    /**
     * Number of entries with a given x bin number (ie the number of times fill was called for these bins).
     * Equivalent to projectionXY().binEntriesX(indexX).
     * @param indexX the x bin number in the external representation: (0...N-1) or OVERFLOW or UNDERFLOW.
     * @return The number of entries for the corresponding bins.
     */
    public int binEntriesX(int indexX) {
        int n = 0;
        for (int j=IAxis.UNDERFLOW_BIN; jprojectionXY().binEntriesY(indexY).
     * @param indexY the y bin number in the external representation: (0...N-1) or OVERFLOW or UNDERFLOW.
     * @return The number of entries for the corresponding bins.
     */
    public int binEntriesY(int indexY) {
        int n = 0;
        for (int i=IAxis.UNDERFLOW_BIN; iprojectionXZ().binEntriesZ(indexZ).
     * @param indexZ the z bin number in the external representation: (0...N-1) or OVERFLOW or UNDERFLOW.
     * @return The number of entries for the corresponding bins.
     */
    public int binEntriesZ(int indexZ) {
        int n = 0;
        for (int i=IAxis.UNDERFLOW_BIN; iprojectionXY().binHeightX(indexX).
     * @param indexX The x bin number in the external representation: (0...N-1) or OVERFLOW or UNDERFLOW.
     * @return The bin height for the corresponding bin.
     *
     */
    public double binHeightX(int indexX) {
        double d = 0;
        for (int j=IAxis.UNDERFLOW_BIN; jprojectionXY().binHeightY(indexY).
     * @param indexY The y bin number in the external representation: (0...N-1) or OVERFLOW or UNDERFLOW.
     * @return The bin height for the corresponding bin.
     *
     */
    public double binHeightY(int indexY) {
        double d = 0;
        for (int i=IAxis.UNDERFLOW_BIN; iprojectionXZ().binHeightZ(indexZ).
     * @param indexZ The y bin number in the external representation: (0...N-1) or OVERFLOW or UNDERFLOW.
     * @return The bin height for the corresponding bin.
     *
     */
    public double binHeightZ(int indexZ) {
        double d = 0;
        for (int i=IAxis.UNDERFLOW_BIN; ixAxis().coordToIndex(coord).
     * @see IAxis#coordToIndex(double)
     * @return The bin's index along the x axis corresponding to the position coordX.
     *
     */
    public int coordToIndexX(double coordX) {
        return xAxis().coordToIndex(coordX);
    }
    
    /**
     * Convenience method, equivalent to yAxis().coordToIndex(coord).
     * @see IAxis#coordToIndex(double)
     * @return The bin's index along the y axis corresponding to the position coordY.
     *
     */
    public int coordToIndexY(double coordY) {
        return yAxis().coordToIndex(coordY);
    }
    
    /**
     * Convenience method, equivalent to zAxis().coordToIndex(coord).
     * @see IAxis#coordToIndex(double)
     * @return The bin's index along the z axis corresponding to the position coordY.
     *
     */
    public int coordToIndexZ(double coordZ) {
        return zAxis().coordToIndex(coordZ);
    }
    
    /**
     * 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");
        binner3D.scale(scaleFactor);
        meanX *= scaleFactor;
        rmsX  *= scaleFactor;
        meanY *= scaleFactor;
        rmsY  *= scaleFactor;
        meanZ *= scaleFactor;
        rmsZ  *= 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(IHistogram3D hist) throws IllegalArgumentException {
        HistMath.checkCompatibility(xAxis(), hist.xAxis());
        HistMath.checkCompatibility(yAxis(), hist.yAxis());
        HistMath.checkCompatibility(zAxis(), hist.zAxis());
        int xbins = xAxis().bins()+2;
        int ybins = yAxis().bins()+2;
        int zbins = zAxis().bins()+2;
        double[][][] newHeights=new double[xbins][ybins][zbins];
        double[][][] newErrors=new double[xbins][ybins][zbins];
        double[][][] newMeanXs  = new double[xbins][ybins][zbins];
        double[][][] newRmsXs   = new double[xbins][ybins][zbins];
        double[][][] newMeanYs  = new double[xbins][ybins][zbins];
        double[][][] newRmsYs   = new double[xbins][ybins][zbins];
        double[][][] newMeanZs  = new double[xbins][ybins][zbins];
        double[][][] newRmsZs   = new double[xbins][ybins][zbins];
        double rmsx2 = 0;
        double rmsy2 = 0;
        double rmsz2 = 0;
        boolean h1Aida = !(hist instanceof Histogram3D);
        int[][][] newEntries = new int[xbins][ybins][zbins];
        for(int i=IAxis.UNDERFLOW_BIN; i= 0 && mj >= 0 && mk >=0 ) || useOutflows() ) {
                        if ( ! Double.isNaN(mx) && ! Double.isNaN(my) && ! Double.isNaN(mz) && ! Double.isInfinite(mx) && ! Double.isInfinite(my) && ! Double.isInfinite(mz) ) {
                            meanX += mx*h;
                            rmsX  += rx*rx*h+mx*mx*h;
                            meanY += my*h;
                            rmsY  += ry*ry*h+my*my*h;
                            meanZ += mz*h;
                            rmsZ  += rz*rz*h+mz*mz*h;
                        }
                        validEntries += e;
                        sumOfWeights += h;
                        sumOfWeightsSquared = h*h;
                    }
                }
            }
        }
    }
    
    public void initHistogram3D( IAxis xAxis, IAxis yAxis, IAxis zAxis, String options ) {
        this.xAxis = xAxis;
        this.yAxis = yAxis;
        this.zAxis = zAxis;
        Map optionMap = hep.aida.ref.AidaUtils.parseOptions( options );
        String type = (String) optionMap.get("type");
        if ( type == null || type.equals("default"))
            binner3D = new BasicBinner3D( xAxis.bins()+2, yAxis.bins()+2, zAxis.bins()+2);
        else if ( type.equals("efficiency") )
            binner3D = new EfficiencyBinner3D( xAxis.bins()+2, yAxis.bins()+2, zAxis.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();
    }
    
    private double meanX = 0, rmsX = 0;
    private double meanY = 0, rmsY = 0;
    private double meanZ = 0, rmsZ = 0;
    private IAxis xAxis, yAxis, zAxis;
    private Binner3D binner3D;
    
}

 

Ads help maintain this website.