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.util.Map; public class Histogram3D extends Histogram implements IHistogram3D { /** * 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. * */ protected 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. * */ protected 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 <tt>projectionXY().binEntriesX(indexX)</tt>. * @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; j<yAxis().bins(); j++) for (int k=IAxis.UNDERFLOW_BIN; k<zAxis().bins(); k++) n += binEntries(indexX,j,k); return n; } /** * Number of entries with a given x bin number (ie the number of times fill was called for these bins). * Equivalent to <tt>projectionXY().binEntriesY(indexY)</tt>. * @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; i<xAxis().bins(); i++) for (int k=IAxis.UNDERFLOW_BIN; k<zAxis().bins(); k++) n += binEntries(i,indexY,k); return n; } /** * Number of entries with a given x bin number (ie the number of times fill was called for these bins). * Equivalent to <tt>projectionXZ().binEntriesZ(indexZ)</tt>. * @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; i<xAxis().bins(); i++) for (int j=IAxis.UNDERFLOW_BIN; j<yAxis().bins(); j++) n += binEntries(i,j,indexZ); return n; } /** * Total height of the corresponding 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 bin height for the corresponding bin. * */ public double binHeight(int indexX, int indexY, int indexZ) { return binner3D.height(mapBinNumber(indexX, xAxis()),mapBinNumber(indexY, yAxis()),mapBinNumber(indexZ, zAxis())); } /** * Total height of the corresponding x bin along y and z. * Equivalent to <tt>projectionXY().binHeightX(indexX)</tt>. * @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; j<yAxis().bins(); j++) for (int k=IAxis.UNDERFLOW_BIN; k<zAxis().bins(); k++) d += binHeight(indexX,j,k); return d; } /** * Total height of the corresponding y bin along x and z. * Equivalent to <tt>projectionXY().binHeightY(indexY)</tt>. * @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; i<xAxis().bins(); i++) for (int k=IAxis.UNDERFLOW_BIN; k<zAxis().bins(); k++) d += binHeight(i,indexY,k); return d; } /** * Total height of the corresponding z bin along x and y. * Equivalent to <tt>projectionXZ().binHeightZ(indexZ)</tt>. * @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; i<xAxis().bins(); i++) for (int j=IAxis.UNDERFLOW_BIN; j<yAxis().bins(); j++) d += binHeight(i,j,indexZ); return d; } /** * The error on 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 error on the corresponding bin. * */ public double binError(int indexX, int indexY, int indexZ) { return binner3D.plusError(mapBinNumber(indexX, xAxis()),mapBinNumber(indexY, yAxis()),mapBinNumber(indexZ, zAxis())); } /** * Get the mean of the whole Histogram as projected on the x axis. It includes all the entries (in and out of range). * @return The mean of the Histogram on the x axis. * */ public double meanX() { if( validEntries != 0) return meanX/sumOfWeights; return 0; } /** * Get the mean of the whole Histogram as projected on the y axis. It includes all the entries (in and out of range). * @return The mean of the Histogram on the y axis. * */ public double meanY() { if( validEntries != 0) return meanY/sumOfWeights; return 0; } /** * Get the mean of the whole Histogram as projected on the z axis. It includes all the entries (in and out of range). * @return The mean of the Histogram on the z axis. * */ public double meanZ() { if( validEntries != 0) return meanZ/sumOfWeights; return 0; } /** * Get the RMS of the whole Histogram as projected on the x axis. It includes all the entries (in and out of range). * @return The RMS of the Histogram on the x axis. * */ public double rmsX(){ if ( validEntries != 0 ) return Math.sqrt(rmsX/sumOfWeights - meanX*meanX/sumOfWeights/sumOfWeights); return 0; } /** * Get the RMS of the whole Histogram as projected on the y axis. It includes all the entries (in and out of range). * @return The RMS of the Histogram on the y axis. * */ public double rmsY(){ if ( validEntries != 0 ) return Math.sqrt(rmsY/sumOfWeights - meanY*meanY/sumOfWeights/sumOfWeights); return 0; } /** * Get the RMS of the whole Histogram as projected on the z axis. It includes all the entries (in and out of range). * @return The RMS of the Histogram on the z axis. * */ public double rmsZ(){ if ( validEntries != 0 ) return Math.sqrt(rmsZ/sumOfWeights - meanZ*meanZ/sumOfWeights/sumOfWeights); return 0; } /** * Get the X axis. * @return The x axis. * */ public IAxis xAxis() { return xAxis; } /** * Get the Y axis. * @return The y axis. * */ public IAxis yAxis() { return yAxis; } /** * Get the Z axis. * @return The z axis. * */ public IAxis zAxis() { return zAxis; } /** * Convenience method, equivalent to <tt>xAxis().coordToIndex(coord)</tt>. * @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 <tt>yAxis().coordToIndex(coord)</tt>. * @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 <tt>zAxis().coordToIndex(coord)</tt>. * @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<xAxis().bins();i++) for(int j=IAxis.UNDERFLOW_BIN; j<yAxis().bins();j++) for(int k=IAxis.UNDERFLOW_BIN; k<zAxis().bins();k++) { double height1 = binHeight(i,j,k); double height2 = hist.binHeight(i,j,k); double h = height1+height2; double meanx1 = binMeanX(i,j,k); double meanx2 = hist.binMeanX(i,j,k); meanx1 = HistUtils.isValidDouble(meanx1) ? meanx1 : 0; meanx2 = HistUtils.isValidDouble(meanx2) ? meanx2 : 0; double mx = 0; double rmsx1 = binRmsX(i,j,k); double rx = 0; double meany1 = binMeanY(i,j,k); double meany2 = hist.binMeanY(i,j,k); meany1 = HistUtils.isValidDouble(meany1) ? meany1 : 0; meany2 = HistUtils.isValidDouble(meany2) ? meany2 : 0; double my = 0; double rmsy1 = binRmsY(i,j,k); double ry = 0; double meanz1 = binMeanZ(i,j,k); double meanz2 = hist.binMeanZ(i,j,k); meanz1 = HistUtils.isValidDouble(meanz1) ? meanz1 : 0; meanz2 = HistUtils.isValidDouble(meanz2) ? meanz2 : 0; double mz = 0; double rmsz1 = binRmsZ(i,j,k); if (h1Aida) { rmsx2 = (hist.xAxis().binUpperEdge(i)-hist.xAxis().binLowerEdge(i))/Math.sqrt(12); rmsy2 = (hist.yAxis().binUpperEdge(j)-hist.yAxis().binLowerEdge(j))/Math.sqrt(12); rmsy2 = (hist.zAxis().binUpperEdge(k)-hist.zAxis().binLowerEdge(k))/Math.sqrt(12); } else { rmsx2 = ((Histogram3D) hist).binRmsX(i, j, k); rmsy2 = ((Histogram3D) hist).binRmsY(i, j, k); rmsz2 = ((Histogram3D) hist).binRmsZ(i, j, k); } double rz = 0; if ( h != 0 ) { mx = ( meanx1*height1 + meanx2*height2 )/(height1+height2); rx = Math.sqrt(((rmsx1*rmsx1*height1 + meanx1*meanx1*height1)+(rmsx2*rmsx2*height2 + meanx2*meanx2*height2))/h - mx*mx); my = ( meany1*height1 + meany2*height2 )/(height1+height2); ry = Math.sqrt(((rmsy1*rmsy1*height1 + meany1*meany1*height1)+(rmsy2*rmsy2*height2 + meany2*meany2*height2))/h - my*my); mz = ( meanz1*height1 + meanz2*height2 )/(height1+height2); rz = Math.sqrt(((rmsz1*rmsz1*height1 + meanz1*meanz1*height1)+(rmsz2*rmsz2*height2 + meanz2*meanz2*height2))/h - mz*mz); } int binx = mapBinNumber(i,xAxis()); int biny = mapBinNumber(j,yAxis()); int binz = mapBinNumber(k,zAxis()); newHeights[binx][biny][binz] = h; newErrors [binx][biny][binz] = Math.sqrt( Math.pow(binError(i,j,k),2) + Math.pow(hist.binError(i,j,k),2) ); newEntries[binx][biny][binz] = binEntries(i,j,k)+hist.binEntries(i,j,k); newMeanXs [binx][biny][binz] = mx; newRmsXs [binx][biny][binz] = rx; newMeanYs [binx][biny][binz] = my; newRmsYs [binx][biny][binz] = ry; newMeanZs [binx][biny][binz] = mz; newRmsZs [binx][biny][binz] = rz; } setContents(newHeights,newErrors,newEntries,newMeanXs,newRmsXs,newMeanYs,newRmsYs,newMeanZs,newRmsZs); if (isValid) fireStateChanged(); } /** * * All the non-AIDA methods should go below this point. * */ public void setMeanX(double meanX) { this.meanX = meanX*sumOfWeights; } public void setRmsX(double rmsX) { this.rmsX = rmsX*rmsX*sumOfWeights + meanX()*meanX()*sumOfWeights; } public void setMeanY(double meanY) { this.meanY = meanY*sumOfWeights; } public void setRmsY(double rmsY) { this.rmsY = rmsY*rmsY*sumOfWeights + meanY()*meanY()*sumOfWeights; } public void setMeanZ(double meanZ) { this.meanZ = meanZ*sumOfWeights; } public void setRmsZ(double rmsZ) { this.rmsZ = rmsZ*rmsZ*sumOfWeights + meanZ()*meanZ()*sumOfWeights; } /** * Get the mean of a bin along the x axis. * @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 mean of the corresponding bin along x. If the bin has zero height, zero is returned. * */ public double binMeanX(int indexX, int indexY, int indexZ) { int binx = mapBinNumber(indexX, xAxis()); int biny = mapBinNumber(indexY, yAxis()); int binz = mapBinNumber(indexZ, zAxis()); double m = binner3D.meanX(binx, biny, binz); return Double.isNaN(m) ? xAxis().binCenter(indexX) : m; } /** * Get the mean of a bin along the y axis. * @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 mean of the corresponding bin along y. If the bin has zero height, zero is returned. * */ public double binMeanY(int indexX, int indexY, int indexZ) { int binx = mapBinNumber(indexX, xAxis()); int biny = mapBinNumber(indexY, yAxis()); int binz = mapBinNumber(indexZ, zAxis()); double m = binner3D.meanY(binx, biny, binz); return Double.isNaN(m) ? yAxis().binCenter(indexY) : m; } /** * Get the mean of a bin along the z axis. * @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 mean of the corresponding bin along z. If the bin has zero height, zero is returned. * */ public double binMeanZ(int indexX, int indexY, int indexZ) { int binx = mapBinNumber(indexX, xAxis()); int biny = mapBinNumber(indexY, yAxis()); int binz = mapBinNumber(indexZ, zAxis()); double m = binner3D.meanZ(binx, biny, binz); return Double.isNaN(m) ? zAxis().binCenter(indexZ) : m; } /** * Get the RMS of a bin along the x axis. * @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 RMS of the corresponding bin along x. If the bin has zero height, zero is returned. * */ public double binRmsX(int indexX, int indexY, int indexZ) { int binx = mapBinNumber(indexX, xAxis()); int biny = mapBinNumber(indexY, yAxis()); int binz = mapBinNumber(indexZ, zAxis()); double r = binner3D.rmsX(binx, biny, binz); return Double.isNaN(r) ? xAxis().binWidth(indexX) : r; } /** * Get the RMS of a bin along the y axis. * @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 RMS of the corresponding bin along y. If the bin has zero height, zero is returned. * */ public double binRmsY(int indexX, int indexY, int indexZ) { int binx = mapBinNumber(indexX, xAxis()); int biny = mapBinNumber(indexY, yAxis()); int binz = mapBinNumber(indexZ, zAxis()); double r = binner3D.rmsY(binx, biny, binz); return Double.isNaN(r) ? yAxis().binWidth(indexY) : r; } /** * Get the RMS of a bin along the z axis. * @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 RMS of the corresponding bin along z. If the bin has zero height, zero is returned. * */ public double binRmsZ(int indexX, int indexY, int indexZ) { int binx = mapBinNumber(indexX, xAxis()); int biny = mapBinNumber(indexY, yAxis()); int binz = mapBinNumber(indexZ, zAxis()); double r = binner3D.rmsZ(binx, biny, binz); return Double.isNaN(r) ? zAxis().binWidth(indexZ) : r; } /** * Set the error on this bin. * @param indexX the bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @param indexY the bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @param indexZ the bin number (0...N-1) or OVERFLOW or UNDERFLOW. */ public void setBinError(int indexX, int indexY, int indexZ, double error) { int binx = mapBinNumber(indexX, xAxis()); int biny = mapBinNumber(indexY, yAxis()); int binz = mapBinNumber(indexZ, zAxis()); binner3D.setBinContent(binx,biny,binz,binEntries(indexX,indexY,indexZ),binHeight(indexX,indexY,indexZ),error, error,binMeanX(indexX,indexY,indexZ),binRmsX(indexX,indexY,indexZ),binMeanY(indexX,indexY,indexZ),binRmsY(indexX,indexY,indexZ),binMeanZ(indexX,indexY,indexZ),binRmsZ(indexX,indexY,indexZ)); } /** * Set the content of the whole Histogram at once. This is a convenience method for saving/restoring Histograms. * Of the arguments below the heights array cannot be null. The errors array should in general be non-null, but this depends on * the specific binner. * The entries array can be null, in which case the entry of a bin is taken to be the integer part of the height. * If the means array is null, the mean is defaulted to the geometric center of the bin. * If the rms array is null, the rms is taken to be the bin width over the root of 12. * * * @param heights The bin heights * @param errors The bin errors * @param entries The bin entries * @param meanXs The means of the bin along the x axis * @param rmsXs The rmss of the bin along the x axis * @param meanYs The means of the bin along the y axis * @param rmsYs The rmss of the bin along the y axis * @param meanZs The means of the bin along the z axis * @param rmsZs The rmss of the bin along the z axis * */ public void setContents(double[][][] heights, double[][][] errors, int[][][] entries, double[][][] meanXs, double[][][] rmsXs, double[][][] meanYs, double[][][] rmsYs, double[][][] meanZs, double[][][]rmsZs) { reset(); for (int i=0; i<xAxis.bins()+2; i++) { int mi; if ( i == 0 ) mi = IAxis.UNDERFLOW_BIN; else if ( i == xAxis().bins()+1 ) mi = IAxis.OVERFLOW_BIN; else mi = i - 1; for (int j=0; j<yAxis().bins()+2; j++) { int mj; if ( j == 0 ) mj = IAxis.UNDERFLOW_BIN; else if ( j == yAxis().bins()+1 ) mj = IAxis.OVERFLOW_BIN; else mj = j - 1; for (int k=0; k<zAxis.bins()+2; k++) { double h = heights[i][j][k]; int mk; if ( k == 0 ) mk = IAxis.UNDERFLOW_BIN; else if ( k == zAxis().bins()+1 ) mk = IAxis.OVERFLOW_BIN; else mk = k - 1; double mx; if ( meanXs != null ) mx = meanXs[i][j][k]; else mx = (xAxis().binLowerEdge(mi)+xAxis().binUpperEdge(mi))/2.; double my; if ( meanYs != null ) my = meanYs[i][j][k]; else my = (yAxis().binLowerEdge(mj)+yAxis().binUpperEdge(mj))/2.; double mz; if ( meanZs != null ) mz = meanZs[i][j][k]; else mz = (zAxis().binLowerEdge(mk)+zAxis().binUpperEdge(mk))/2.; double rx; if ( rmsXs != null ) rx = rmsXs[i][j][k]; else rx = (xAxis().binUpperEdge(mi)-xAxis().binLowerEdge(mi))/Math.sqrt(12); double ry; if ( rmsYs != null ) ry = rmsYs[i][j][k]; else ry = (yAxis().binUpperEdge(mj)-yAxis().binLowerEdge(mj))/Math.sqrt(12); double rz; if ( rmsZs != null ) rz = rmsZs[i][j][k]; else rz = (zAxis().binUpperEdge(mk)-zAxis().binLowerEdge(mk))/Math.sqrt(12); int e; if ( entries != null ) e = entries[i][j][k]; else e = (int)h; binner3D.setBinContent(i,j,k,e,h,errors[i][j][k],errors[i][j][k],mx,rx,my,ry,mz,rz); h = binner3D.height(i,j,k); allEntries+= e; if ( ( mi >= 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; }