package hep.aida.ref.pdf;
import hep.aida.ITuple;
import hep.aida.ref.tuple.Tuple;
import java.util.Random;
/**
* An utility class to generate toy MC data sets distributed according to a given function.
*
* @author The FreeHEP team @ SLAC.
*
*/
public abstract class FunctionMcStudy {
public static ITuple generateTuple(Function f, int nEntries) {
double maxHeight = f.maxValue();
if ( maxHeight == Double.NaN )
maxHeight = evaluateMaxHeight(f,nEntries/10);
maxHeight *= 1.2;
return generateTuple(f,nEntries,maxHeight);
}
protected static ITuple generateTuple(Function f, int nEntries, double maxHeight) {
int dim = f.numberOfDependents();
Dependent[] deps = new Dependent[dim];
String[] columnNames = new String[dim+1];
Class[] columnTypes = new Class[dim+1];
for ( int i = 0; i < dim; i++ ) {
columnNames[i] = f.getDependent(i).name();
columnTypes[i] = Double.TYPE;
deps[i] = f.getDependent(i);
}
columnNames[dim] = "functionValue";
columnTypes[dim] = Double.TYPE;
Tuple t = new Tuple("tup", "", columnNames, columnTypes, "");
Random r = new Random();
double x;
int count = 0;
while(true) {
for ( int j = 0; j < dim; j++ ) {
x = deps[j].range().generatePoint();
deps[j].setValue(x);
t.fill(j,x);
}
x = f.functionValue();
t.fill(dim,x);
if ( x > maxHeight ) {
System.out.println("Function value "+x+" exceeds maximum "+maxHeight+". Increasing maximum by 20% and restarting the MC study.");
return generateTuple(f,nEntries, maxHeight*1.2);
}
if ( r.nextDouble()*maxHeight < x ) {
t.addRow();
if ( t.rows() == nEntries )
return t;
}
}
}
private static double evaluateMaxHeight(Function f, int entries) {
int dim = f.numberOfDependents();
Dependent[] deps = new Dependent[dim];
for ( int i = 0; i < dim; i++ )
deps[i] = f.getDependent(i);
double maxHeight = 0;
double x;
for ( int i = 0; i < entries; i++ ) {
for ( int j = 0; j < dim; j++ ) {
x = deps[j].range().generatePoint();
deps[j].setValue(x);
}
x = f.functionValue();
if ( x > maxHeight )
maxHeight = x;
}
return maxHeight;
}
}