package hep.aida.util.comparison;
import hep.aida.ext.IComparisonAlgorithm;
import hep.aida.ext.IComparisonData;
import hep.aida.ext.IComparisonResult;
import hep.aida.ref.AidaUtils;
import java.util.Map;
/**
*
* @author The FreeHEP team @ SLAC.
*
*/
public abstract class AbstractComparisonAlgorithm implements IComparisonAlgorithm {
private Map optionsMap;
public static final int ONLY_BINNED_DATA = 0;
public static final int ONLY_UNBINNED_DATA = 1;
public static final int ANY_DATA = 2;
public static final int ONLY_SAME_NUMBER_OF_EVENTS = 0;
public static final int ANY_NUMBER_OF_EVENTS = 1;
private int dataType;
private int eventsType;
private double rejectionLevel = 0.05;
AbstractComparisonAlgorithm(int dataType, int eventsType) {
this.dataType = dataType;
this.eventsType = eventsType;
}
public IComparisonResult compare(IComparisonData d1, IComparisonData d2, String options) {
if ( ! canCompare(d1, d2) )
throw new IllegalArgumentException("This algorithm "+algorithmNames()[0]+" cannot compare the given data sets.");
this.optionsMap = AidaUtils.parseOptions(options);
applyOptions();
setRejectionLevel();
ComparisonResult result = new ComparisonResult();
result.setMatchBounds(matchLowerBound(), matchUpperBound());
result.setQuality( quality(d1,d2) );
result.setnDof( nDof(d1,d2) );
return result;
}
public abstract double quality(IComparisonData d1, IComparisonData d2);
public void applyOptions() {
}
public int nDof(IComparisonData d1, IComparisonData d2) {
return d1.nPoints();
}
public double matchLowerBound() {
return rejectionLevel();
}
public double matchUpperBound() {
return 1;
}
public boolean isOptionSet(String option) {
return optionsMap.containsKey(option);
}
public String optionValue(String option) {
return (String)optionsMap.get(option);
}
public abstract String[] algorithmNames();
public void setRejectionLevel() {
String rejectionLevelStr = optionValue("rejectionLevel");
if ( rejectionLevelStr != null )
rejectionLevel = Double.valueOf(rejectionLevelStr).doubleValue();
}
public double rejectionLevel() {
return rejectionLevel;
}
public double[] getCumulativeArray(IComparisonData d) {
int nPoints = d.nPoints();
double[] cumulativeWeights = new double[nPoints];
double sumOfWeights = 0;
for ( int i = 0; i < nPoints; i++ ) {
double weight = d.weight(i);
if ( weight < 0 )
weight = 0;
sumOfWeights += weight;
cumulativeWeights[i] = sumOfWeights;
}
if ( sumOfWeights != 0 )
for( int i=0; i < nPoints; i++ )
cumulativeWeights[i] /= sumOfWeights;
return cumulativeWeights;
}
public boolean canCompare(IComparisonData d1, IComparisonData d2) {
if ( d1.type() != d2.type() )
throw new IllegalArgumentException("Cannot compare a binned data set with an unbinned one.");
if ( d1.type() == IComparisonData.BINNED_DATA && dataType == ONLY_UNBINNED_DATA )
return false;
if ( d1.type() == IComparisonData.UNBINNED_DATA && dataType == ONLY_BINNED_DATA )
return false;
if ( d1.type() == IComparisonData.BINNED_DATA )
if ( ! isBinningCompatible(d1, d2) )
return false;
if ( eventsType == ONLY_SAME_NUMBER_OF_EVENTS )
if ( d1.nPoints() != d2.nPoints() )
return false;
return true;
}
private boolean isBinningCompatible(IComparisonData d1, IComparisonData d2 ) {
int nBins = d1.nPoints();
if ( nBins != d2.nPoints() )
return false;
for ( int i = 0; i < nBins; i++ )
if ( d1.value(i) != d2.value(i) )
return false;
return true;
}
public double sumOfWeights(IComparisonData d) {
double sumOfWeights = 0;
for ( int i = 0; i < d.nPoints(); i++ )
sumOfWeights += d.weight(i);
return sumOfWeights;
}
public int entries(IComparisonData d) {
int entries = 0;
for ( int i = 0; i < d.nPoints(); i++ )
entries += d.entries(i);
return entries;
}
}