package hep.aida.ref;
import hep.aida.IAxis;
import hep.aida.IHistogram;
import hep.aida.IHistogram2D;
import hep.aida.IHistogram3D;
/**
Abstract base class extracting and implementing most of the redundancy of the interface.
@author Wolfgang Hoschek, Tony Johnson, and others.
@version 1.0, 23/03/2000
*/
abstract class AbstractHistogram3D extends Histogram implements IHistogram3D
{
protected IAxis xAxis, yAxis, zAxis;
AbstractHistogram3D(String title)
{
super(title);
}
public int allEntries()
{
int n = 0;
for (int i=xAxis.bins(); --i >= -2;)
for (int j=yAxis.bins(); --j >= -2;)
for (int k=zAxis.bins(); --k >= -2;)
{
n += binEntries(i,j,k);
}
return n;
}
public int dimensions()
{
return 3;
}
public int entries()
{
int n = 0;
for (int i=0; i<xAxis.bins(); i++)
for (int j=0; j<yAxis.bins(); j++)
for (int k=0;k<zAxis.bins(); k++)
{
n += binEntries(i,j,k);
}
return n;
}
public int extraEntries()
{
return allEntries() - entries();
}
public void fill(double x, double y, double z)
{
fill(x,y,z,1);
}
/**
* The precise meaning of the arguments to the public slice
* methods is somewhat ambiguous, so we define this internal
* slice method and clearly specify its arguments.
* <p>
* <b>Note 0</b>indexX1 and indexX2 use our INTERNAL bin numbering scheme
* <b>Note 1</b>The slice is done between indexX1 and indexX2 INCLUSIVE
* <b>Note 2</b>indexX1 and indexX2 may include the use of under and over flow bins
* <b>Note 3</b>There is no note 3 (yet)
*/
protected abstract IHistogram2D internalSliceXY(String title, int indexZ1, int indexZ2);
/**
* The precise meaning of the arguments to the public slice
* methods is somewhat ambiguous, so we define this internal
* slice method and clearly specify its arguments.
* <p>
* <b>Note 0</b>indexY1 and indexY2 use our INTERNAL bin numbering scheme
* <b>Note 1</b>The slice is done between indexY1 and indexY2 INCLUSIVE
* <b>Note 2</b>indexY1 and indexY2 may include the use of under and over flow bins
* <b>Note 3</b>There is no note 3 (yet)
*/
protected abstract IHistogram2D internalSliceXZ(String title, int indexY1, int indexY2);
/**
* The precise meaning of the arguments to the public slice
* methods is somewhat ambiguous, so we define this internal
* slice method and clearly specify its arguments.
* <p>
* <b>Note 0</b>indexX1 and indexX2 use our INTERNAL bin numbering scheme
* <b>Note 1</b>The slice is done between indexX1 and indexX2 INCLUSIVE
* <b>Note 2</b>indexX1 and indexX2 may include the use of under and over flow bins
* <b>Note 3</b>There is no note 3 (yet)
*/
protected abstract IHistogram2D internalSliceYZ(String title, int indexX1, int indexX2);
/**
* Package private method to map from the external representation of bin
* number to our internal representation of bin number
*/
int mapX(int index)
{
int bins = xAxis.bins() + 2;
if (index >= bins) throw new IllegalArgumentException("bin="+index);
if (index >= 0) return index+1;
if (index == IHistogram.UNDERFLOW) return 0;
if (index == IHistogram.OVERFLOW) return bins-1;
throw new IllegalArgumentException("bin="+index);
}
/**
* Package private method to map from the external representation of bin
* number to our internal representation of bin number
*/
int mapY(int index)
{
int bins = yAxis.bins() + 2;
if (index >= bins) throw new IllegalArgumentException("bin="+index);
if (index >= 0) return index+1;
if (index == IHistogram.UNDERFLOW) return 0;
if (index == IHistogram.OVERFLOW) return bins-1;
throw new IllegalArgumentException("bin="+index);
}
/**
* Package private method to map from the external representation of bin
* number to our internal representation of bin number
*/
int mapZ(int index)
{
int bins = zAxis.bins() + 2;
if (index >= bins) throw new IllegalArgumentException("bin="+index);
if (index >= 0) return index+1;
if (index == IHistogram.UNDERFLOW) return 0;
if (index == IHistogram.OVERFLOW) return bins-1;
throw new IllegalArgumentException("bin="+index);
}
public int[] minMaxBins()
{
double minValue = Double.MAX_VALUE;
double maxValue = Double.MIN_VALUE;
int minBinX = -1;
int minBinY = -1;
int minBinZ = -1;
int maxBinX = -1;
int maxBinY = -1;
int maxBinZ = -1;
for (int i=xAxis.bins(); --i >= 0; ) {
for (int j=yAxis.bins(); --j >= 0; ) {
for (int k=zAxis.bins(); --k >= 0; ) {
double value = binHeight(i,j,k);
if (value < minValue) {
minValue = value;
minBinX = i;
minBinY = j;
minBinZ = k;
}
if (value > maxValue) {
maxValue = value;
maxBinX = i;
maxBinY = j;
maxBinZ = k;
}
}
}
}
int[] result = {minBinX,minBinY,minBinZ, maxBinX,maxBinY,maxBinZ};
return result;
}
public IHistogram2D projectionXY()
{
String newTitle = title() + " (projectionXY)";
return internalSliceXY(newTitle,mapZ(IHistogram.UNDERFLOW),mapZ(IHistogram.OVERFLOW));
}
public IHistogram2D projectionXZ()
{
String newTitle = title() + " (projectionXZ)";
return internalSliceXZ(newTitle,mapY(IHistogram.UNDERFLOW),mapY(IHistogram.OVERFLOW));
}
public IHistogram2D projectionYZ()
{
String newTitle = title() + " (projectionYZ)";
return internalSliceYZ(newTitle,mapX(IHistogram.UNDERFLOW),mapX(IHistogram.OVERFLOW));
}
public IHistogram2D sliceXY(int indexZ )
{
return sliceXY(indexZ,indexZ);
}
public IHistogram2D sliceXY(int indexZ1, int indexZ2)
{
int start = mapZ(indexZ1);
int stop = mapZ(indexZ2);
String newTitle = title() + " (sliceXY ["+indexZ1+":"+indexZ2+"])";
return internalSliceXY(newTitle,start,stop);
}
public IHistogram2D sliceXZ(int indexY )
{
return sliceXZ(indexY,indexY);
}
public IHistogram2D sliceXZ(int indexY1, int indexY2)
{
int start = mapY(indexY1);
int stop = mapY(indexY2);
String newTitle = title() + " (sliceXZ ["+indexY1+":"+indexY2+"])";
return internalSliceXY(newTitle,start,stop);
}
public IHistogram2D sliceYZ(int indexX )
{
return sliceYZ(indexX,indexX);
}
public IHistogram2D sliceYZ(int indexX1, int indexX2)
{
int start = mapX(indexX1);
int stop = mapX(indexX2);
String newTitle = title() + " (sliceYZ ["+indexX1+":"+indexX2+"])";
return internalSliceYZ(newTitle,start,stop);
}
public double sumAllBinHeights()
{
double n = 0;
for (int i=xAxis.bins(); --i >= -2;)
for (int j=yAxis.bins(); --j >= -2;)
for (int k=zAxis.bins(); --k >= -2;)
{
n += binHeight(i,j,k);
}
return n;
}
public double sumBinHeights()
{
double n = 0;
for (int i=0; i<xAxis.bins(); i++)
for (int j=0; j<yAxis.bins(); j++)
for (int k=0; k<zAxis.bins(); k++)
{
n += binHeight(i,j,k);
}
return n;
}
public double sumExtraBinHeights()
{
return sumAllBinHeights() - sumBinHeights();
}
public IAxis xAxis()
{
return xAxis;
}
public IAxis yAxis()
{
return yAxis;
}
public IAxis zAxis()
{
return zAxis;
}
}