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; } }