/*
* BinnerMath.java
*
* Created on March 5, 2007, 10:49 AM
*
*/
package hep.aida.ref.histogram.binner;
/**
*
* @author serbo
*/
public class BinnerMath {
public static void add(Binner1D newBinner, Binner1D b1, Binner1D b2) throws IllegalArgumentException{
checkCompatibility(b1, b2);
checkCompatibility(newBinner, b2);
for (int i=0; i<b1.bins(); i++) {
int e = b1.entries(i) + b2.entries(i);
double h = b1.height(i) + b2.height(i);
double sumWW = b1.sumWW(i) + b2.sumWW(i);
double sumXW = b1.sumXW(i) + b2.sumXW(i);
double sumXXW = b1.sumXXW(i) +b2.sumXXW(i);
double d = b1.binCenter(i) - b2.binCenter(i);
if (d != 0) {
sumXXW -= d*(2*b2.sumXW(i) - d*b2.height(i));
sumXW -= d*b2.height(i);
}
double ep = Math.sqrt(b1.plusError(i)*b1.plusError(i) + b2.plusError(i)*b2.plusError(i));
double em = Math.sqrt(b1.minusError(i)*b1.plusError(i) + b2.minusError(i)*b2.plusError(i));
newBinner.setBinContent(i, b1.binCenter(i), e, h, ep, em, sumWW, sumXW, sumXXW);
}
}
// Assume uncorrelated statistics: sumWW = sumWW1 + sumWW2
public static void sub(Binner1D newBinner, Binner1D b1, Binner1D b2) throws IllegalArgumentException{
checkCompatibility(b1, b2);
checkCompatibility(newBinner, b2);
for (int i=0; i<b1.bins(); i++) {
int e = b1.entries(i) - b2.entries(i);
double h = b1.height(i) - b2.height(i);
double sumWW = b1.sumWW(i) + b2.sumWW(i);
double sumXW = b1.sumXW(i) - b2.sumXW(i);
double sumXXW = b1.sumXXW(i) - b2.sumXXW(i);
double d = b1.binCenter(i) - b2.binCenter(i);
if (d != 0) {
sumXXW += d*(2*b2.sumXW(i) - d*b2.height(i));
sumXW += d*b2.height(i);
}
double ep = Math.sqrt(b1.plusError(i)*b1.plusError(i) + b2.plusError(i)*b2.plusError(i));
double em = Math.sqrt(b1.minusError(i)*b1.plusError(i) + b2.minusError(i)*b2.plusError(i));
newBinner.setBinContent(i, b1.binCenter(i), e, h, ep, em, sumWW, sumXW, sumXXW);
}
}
// Treat multiplication as bin-dependent scaling
// Scaling factor has an error
public static void mul(Binner1D newBinner, Binner1D b1, Binner1D b2) throws IllegalArgumentException{
checkCompatibility(b1, b2);
checkCompatibility(newBinner, b2);
for (int i=0; i<b1.bins(); i++) {
int e = b1.entries(i);
double h = b1.height(i)*b2.height(i);
double sumXW = b1.sumXW(i)*b2.height(i);
double sumXXW = b1.sumXXW(i)*b2.height(i);
//double sumWW = b1.sumWW(i)*b2.height(i)*b2.height(i);
double sumWW = sumWW_Mul(b1.height(i), b1.sumWW(i), b2.height(i), b2.sumWW(i));
double ep = errorMul(b1.plusError(i), b1.height(i), b2.plusError(i), b2.height(i));
double em = errorMul(b1.minusError(i) ,b1.height(i), b2.minusError(i), b2.height(i));
newBinner.setBinContent(i, b1.binCenter(i), e, h, ep, em, sumWW, sumXW, sumXXW);
}
}
// Treat division as bin-dependent scaling
// Scaling factor has an error
public static void div(Binner1D newBinner, Binner1D b1, Binner1D b2) throws IllegalArgumentException{
checkCompatibility(b1, b2);
checkCompatibility(newBinner, b2);
for (int i=0; i<b1.bins(); i++) {
int e = b1.entries(i);
double h = 0;
double sumXW = b1.sumXW(i);
double sumXXW = b1.sumXXW(i);
double sumWW = Double.NaN;
double ep = Double.NaN;
double em = Double.NaN;
if (b2.height(i) != 0) {
h = b1.height(i)/b2.height(i);
sumXW = b1.sumXW(i)/b2.height(i);
sumXXW = b1.sumXXW(i)/b2.height(i);
sumWW = sumWW_Div(b1.height(i), b1.sumWW(i), b2.height(i), b2.sumWW(i));
ep = errorDiv(b1.plusError(i), b1.height(i), b2.plusError(i), b2.height(i));
em = errorDiv(b1.minusError(i) ,b1.height(i), b2.minusError(i), b2.height(i));
}
newBinner.setBinContent(i, b1.binCenter(i), e, h, ep, em, sumWW, sumXW, sumXXW);
}
}
public static boolean isValidDouble(double d) {
if ( Double.isNaN(d) )
return false;
if ( Double.isInfinite(d) )
return false;
return true;
}
static void checkCompatibility(Binner1D binner1, Binner1D binner2) throws IllegalArgumentException {
if (binner1.bins() != binner2.bins()) {
String message = "Different number of bins: n1="+binner1.bins()+", n2="+binner2.bins();
throw new IllegalArgumentException(message);
}
}
private static double errorMul(double e1, double l1, double e2, double l2) {
return Math.sqrt(Math.pow(e1*l2, 2) + Math.pow(l1*e2, 2));
}
private static double sumWW_Mul(double h1, double sumWW1, double h2, double sumWW2) {
return sumWW1*h2*h2 + sumWW2*h1*h1;
}
private static double errorDiv(double e1, double l1, double e2, double l2) {
return Math.sqrt(Math.pow(e1/l2, 2) + Math.pow(e2*l1/(l2*l2), 2));
}
private static double sumWW_Div(double h1, double sumWW1, double h2, double sumWW2) {
return (sumWW1 +sumWW2*Math.pow(h1/h2, 2))/(h2*h2);
}
}