package hep.aida.bin;
import cern.colt.list.DoubleArrayList;
import cern.jet.stat.Descriptive;
/**
* Abstract base class for all 1-dimensional bins consumes <tt>double</tt> elements.
* First see the <a href="package-summary.html">package summary</a> and javadoc <a href="package-tree.html">tree view</a> to get the broad picture.
* <p>
* This class is fully thread safe (all public methods are synchronized).
* Thus, you can have one or more threads adding to the bin as well as one or more threads reading and viewing the statistics of the bin <i>while it is filled</i>.
* For high performance, add data in large chunks (buffers) via method <tt>addAllOf</tt> rather than piecewise via method <tt>add</tt>.
*
* @author wolfgang.hoschek@cern.ch
* @version 0.9, 03-Jul-99
*/
public abstract class AbstractBin1D extends AbstractBin implements cern.colt.buffer.DoubleBufferConsumer {
/**
* Makes this class non instantiable, but still let's others inherit from it.
*/
protected AbstractBin1D() {
}
/**
* Adds the specified element to the receiver.
*
* @param element element to be appended.
*/
public abstract void add(double element);
/**
* Adds all values of the specified list to the receiver.
* @param list the list of which all values shall be added.
*/
public final synchronized void addAllOf(DoubleArrayList list) {
addAllOfFromTo(list,0,list.size()-1);
}
/**
* Adds the part of the specified list between indexes <tt>from</tt> (inclusive) and <tt>to</tt> (inclusive) to the receiver.
* You may want to override this method for performance reasons.
*
* @param list the list of which elements shall be added.
* @param from the index of the first element to be added (inclusive).
* @param to the index of the last element to be added (inclusive).
* @throws IndexOutOfBoundsException if <tt>list.size()>0 && (from<0 || from>to || to>=list.size())</tt>.
*/
public synchronized void addAllOfFromTo(DoubleArrayList list, int from, int to) {
for (int i=from; i<=to; i++) add(list.getQuick(i));
}
/**
* Constructs and returns a streaming buffer connected to the receiver.
* Whenever the buffer is full it's contents are automatically flushed to <tt>this</tt>.
* (Addding elements via a buffer to a bin is significantly faster than adding them directly.)
* @param capacity the number of elements the buffer shall be capable of holding before overflowing and flushing to the receiver.
* @return a streaming buffer having the receiver as target.
*/
public synchronized cern.colt.buffer.DoubleBuffer buffered(int capacity) {
return new cern.colt.buffer.DoubleBuffer(this,capacity);
}
/**
* Computes the deviations from the receiver's measures to another bin's measures.
* @param other the other bin to compare with
* @return a summary of the deviations.
*/
public String compareWith(AbstractBin1D other) {
StringBuffer buf = new StringBuffer();
buf.append("\nDifferences [percent]");
buf.append("\nSize: "+relError(size(),other.size()) +" %");
buf.append("\nSum: "+relError(sum(),other.sum())+" %");
buf.append("\nSumOfSquares: "+relError(sumOfSquares(),other.sumOfSquares()) +" %");
buf.append("\nMin: "+relError(min(),other.min()) +" %");
buf.append("\nMax: "+relError(max(),other.max()) +" %");
buf.append("\nMean: "+relError(mean(),other.mean()) +" %");
buf.append("\nRMS: "+relError(rms(),other.rms()) +" %");
buf.append("\nVariance: "+relError(variance(),other.variance()) +" %");
buf.append("\nStandard deviation: "+relError(standardDeviation(),other.standardDeviation()) +" %");
buf.append("\nStandard error: "+relError(standardError(),other.standardError()) +" %");
buf.append("\n");
return buf.toString();
}
/**
* Returns whether two bins are equal;
* They are equal if the other object is of the same class or a subclass of this class and both have the same size, minimum, maximum, sum and sumOfSquares.
*/
public boolean equals(Object object) {
if (!(object instanceof AbstractBin1D)) return false;
AbstractBin1D other = (AbstractBin1D) object;
return size()==other.size() && min()==other.min() && max()==other.max()
&& sum()==other.sum() && sumOfSquares()==other.sumOfSquares();
}
/**
* Returns the maximum.
*/
public abstract double max();
/**
* Returns the arithmetic mean, which is <tt>Sum( x[i] ) / size()</tt>.
*/
public synchronized double mean() {
return sum() / size();
}
/**
* Returns the minimum.
*/
public abstract double min();
/**
* Computes the relative error (in percent) from one measure to another.
*/
protected double relError(double measure1, double measure2) {
return 100 * (1 - measure1 / measure2);
}
/**
* Returns the rms (Root Mean Square), which is <tt>Math.sqrt( Sum( x[i]*x[i] ) / size() )</tt>.
*/
public synchronized double rms() {
return Descriptive.rms(size(), sumOfSquares());
}
/**
* Returns the sample standard deviation, which is <tt>Math.sqrt(variance())</tt>.
*/
public synchronized double standardDeviation() {
return Math.sqrt(variance());
}
/**
* Returns the sample standard error, which is <tt>Math.sqrt(variance() / size())</tt>
*/
public synchronized double standardError() {
return Descriptive.standardError(size(),variance());
}
/**
* Returns the sum of all elements, which is <tt>Sum( x[i] )</tt>.
*/
public abstract double sum();
/**
* Returns the sum of squares, which is <tt>Sum( x[i] * x[i] )</tt>.
*/
public abstract double sumOfSquares();
/**
* Returns a String representation of the receiver.
*/
public synchronized String toString() {
StringBuffer buf = new StringBuffer();
buf.append(getClass().getName());
buf.append("\n-------------");
buf.append("\nSize: "+size());
buf.append("\nSum: "+sum());
buf.append("\nSumOfSquares: "+sumOfSquares());
buf.append("\nMin: "+min());
buf.append("\nMax: "+max());
buf.append("\nMean: "+mean());
buf.append("\nRMS: "+rms());
buf.append("\nVariance: "+variance());
buf.append("\nStandard deviation: "+standardDeviation());
buf.append("\nStandard error: "+standardError());
/*
buf.append("\nValue: "+value());
buf.append("\nError(0): "+error(0));
*/
buf.append("\n");
return buf.toString();
}
/**
* Trims the capacity of the receiver to be the receiver's current size.
* Releases any superfluos internal memory.
* An application can use this operation to minimize the storage of the receiver.
* This default implementation does nothing.
*/
public synchronized void trimToSize() {}
/**
* Returns the sample variance, which is <tt>Sum( (x[i]-mean())<sup>2</sup> ) / (size()-1)</tt>.
*/
public synchronized double variance() {
return Descriptive.sampleVariance(size(), sum(), sumOfSquares());
}
}