package hep.aida.ref.root; import hep.aida.IAxis; import hep.aida.IHistogram1D; import hep.aida.IHistogram2D; import hep.aida.IManagedObject; import hep.aida.IProfile; import hep.aida.IProfile1D; import hep.aida.ITuple; import hep.aida.ref.ManagedObject; import hep.aida.ref.histogram.FixedAxis; import hep.aida.ref.histogram.Histogram1D; import hep.aida.ref.histogram.Histogram2D; import hep.aida.ref.histogram.Profile1D; import hep.io.root.RootClassNotFound; import hep.io.root.interfaces.TAxis; import hep.io.root.interfaces.TH1; import hep.io.root.interfaces.TH1D; import hep.io.root.interfaces.TH1F; import hep.io.root.interfaces.TH2; import hep.io.root.interfaces.TH2D; import hep.io.root.interfaces.TH2F; import hep.io.root.interfaces.TKey; import hep.io.root.interfaces.TProfile; import hep.io.root.interfaces.TTree; import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * Adapts Root histograms and Trees to their corresponding AIDA interfaces * @author tonyj * @version $Id */ class Converter { static IManagedObject convert(TKey key, String name, boolean useProxies) throws RootClassNotFound, IOException { IManagedObject result = useProxies ? proxyConvert(key, name) : internalConvert(key, name); if (result == null) { System.err.println("Warning: Ignored " + name + " of type " + key.getObjectClass()); } return result; } private static Histogram1D convert(TH1 h1, String name) { Histogram1D hist = new Histogram1D(); hist.setName(name); TAxis axis = h1.getXaxis(); String xAxisLabel = axis.getTitle(); String yAxisLabel = h1.getYaxis().getTitle(); hist.annotation().addItem("xaxislabel",xAxisLabel,true); hist.annotation().addItem("yaxislabel",yAxisLabel,true); int nBins = axis.getNbins(); double[] values; if (h1 instanceof TH1F) { TH1F th1f = (TH1F) h1; float[] array = th1f.getArray(); values = new double[nBins + 2]; for (int i = 0; i < (nBins + 2); i++) values[i] = array[i]; } else if (h1 instanceof TH1D) { TH1D th1d = (TH1D) h1; values = th1d.getArray(); } else return null; //TODO: Deal with variable bins IAxis xAxis = new FixedAxis(nBins, axis.getXmin(), axis.getXmax()); hist.initHistogram1D(xAxis, null); double[] errors = h1.getSumw2(); if ((errors == null) || (errors.length == 0)) { errors = new double[nBins + 2]; for (int i = 0; i < (nBins + 2); i++) errors[i] = Math.sqrt(values[i]); } else { for (int i = 0; i < (nBins + 2); i++) errors[i] = Math.sqrt(errors[i]); } double sumw = h1.getTsumw(); double sumwx = h1.getTsumwx(); double sumwx2 = h1.getTsumwx2(); double meanx = sumwx / sumw; double rmsx = Math.sqrt((sumwx2 / sumw) - ((sumwx * sumwx) / sumw / sumw)); hist.setContents(values, errors, null, null, null); hist.setNEntries((int) h1.getEntries()); hist.setValidEntries((int) h1.getEntries()-hist.extraEntries()); hist.setMeanAndRms(meanx, rmsx); hist.setTitle(h1.getTitle()); return hist; } private static Histogram2D convert(TH2 h2, String name) { Histogram2D hist = new Histogram2D(); hist.setName(name); TAxis xTAxis = h2.getXaxis(); int nXbins = xTAxis.getNbins(); TAxis yTAxis = h2.getYaxis(); int nYbins = yTAxis.getNbins(); IAxis xAxis = new FixedAxis(nXbins, xTAxis.getXmin(), xTAxis.getXmax()); IAxis yAxis = new FixedAxis(nYbins, yTAxis.getXmin(), yTAxis.getXmax()); hist.initHistogram2D( xAxis, yAxis, null); String xAxisLabel = h2.getXaxis().getTitle(); String yAxisLabel = h2.getYaxis().getTitle(); hist.annotation().addItem("xaxislabel",xAxisLabel,true); hist.annotation().addItem("yaxislabel",yAxisLabel,true); double[][] values; if (h2 instanceof TH2F) { TH2F th2f = (TH2F) h2; float[] array = th2f.getArray(); values = new double[nXbins+2][nYbins+2]; int k = 0; for (int j=0; j < (nYbins + 2); j++) for (int i = 0; i < (nXbins + 2); i++) { values[i][j] = array[k++]; } } else if (h2 instanceof TH2D) { TH2D th2d = (TH2D) h2; double[] array = th2d.getArray(); values = new double[nXbins+2][nYbins+2]; int k = 0; for (int j=0; j < (nYbins + 2); j++) for (int i = 0; i < (nXbins + 2); i++) { values[i][j] = array[k++]; } } else return null; double[] errors = h2.getSumw2(); double[][] errors2d; if ((errors == null) || (errors.length == 0)) { errors2d = new double[nXbins+2][nYbins+2]; for (int i = 0; i < (nXbins + 2); i++) for (int j=0; j < (nYbins + 2); j++) { errors2d[i][j] = Math.sqrt(values[i][j]); } } else { errors2d = new double[nXbins+2][nYbins+2]; int k = 0; for (int j=0; j < (nYbins + 2); j++) for (int i = 0; i < (nXbins + 2); i++) { errors2d[i][j] = errors[k++]; } } double sumw = h2.getTsumw(); double sumwx = h2.getTsumwx(); double sumwx2 = h2.getTsumwx2(); double sumwy = h2.getTsumwy(); double sumwy2 = h2.getTsumwy2(); double meanx = sumwx / sumw; double meany = sumwy / sumw; double rmsx = Math.sqrt((sumwx2 / sumw) - ((sumwx * sumwx) / sumw / sumw)); double rmsy = Math.sqrt((sumwy2 / sumw) - ((sumwy * sumwy) / sumw / sumw)); hist.setContents(values,errors2d,null,null,null,null,null); hist.setNEntries((int) h2.getEntries()); hist.setValidEntries((int) h2.getEntries()- hist.extraEntries()); hist.setMeanX(meanx); hist.setRmsX(rmsx); hist.setMeanY(meany); hist.setRmsY(rmsy); hist.setTitle(h2.getTitle()); return hist; } private static Profile1D convert(TProfile h1, String name) { Profile1D profile = new Profile1D(); profile.setName(name); TAxis axis = h1.getXaxis(); String xAxisLabel = axis.getTitle(); String yAxisLabel = h1.getYaxis().getTitle(); profile.annotation().addItem("xaxislabel",xAxisLabel,true); profile.annotation().addItem("yaxislabel",yAxisLabel,true); int nBins = axis.getNbins(); double[] heights = h1.getArray(); double[] entriesD = h1.getBinEntries(); int[] entries = new int[entriesD.length]; for (int i=0; i<entriesD.length; i++) entries[i] = (int) entriesD[i]; //TODO: Deal with variable bins IAxis xAxis = new FixedAxis(nBins, axis.getXmin(), axis.getXmax()); profile.initProfile1D(xAxis); double[] errors = h1.getSumw2(); if ((errors == null) || (errors.length == 0)) { errors = new double[nBins + 2]; for (int i = 0; i < (nBins + 2); i++) errors[i] = Math.sqrt(heights[i]); } else { for (int i = 0; i < (nBins + 2); i++) errors[i] = Math.sqrt(errors[i]); } double sumw = h1.getTsumw(); double sumwx = h1.getTsumwx(); double sumwx2 = h1.getTsumwx2(); double meanx = sumwx / sumw; double rmsx = Math.sqrt((sumwx2 / sumw) - ((sumwx * sumwx) / sumw / sumw)); profile.setContents(heights, errors, entries, null, null); profile.setNEntries((int) h1.getEntries()); profile.setValidEntries((int) h1.getEntries()-profile.extraEntries()); profile.setMean(meanx); profile.setRms(rmsx); profile.setTitle(h1.getTitle()); return profile; } private static IManagedObject internalConvert(TKey key, String name) throws RootClassNotFound, IOException { Class keyClass = key.getObjectClass().getJavaClass(); if (TProfile.class.isAssignableFrom(keyClass)) return convert((TProfile) key.getObject(), name); else if (TH2.class.isAssignableFrom(keyClass)) return convert((TH2) key.getObject(), name); else if (TH1.class.isAssignableFrom(keyClass)) return convert((TH1) key.getObject(), name); else if (TTree.class.isAssignableFrom(keyClass)) return new TTreeTuple(key, name); else return null; } private static IManagedObject proxyConvert(TKey key, String name) throws RootClassNotFound, IOException { Class keyClass = key.getObjectClass().getJavaClass(); if (TProfile.class.isAssignableFrom(keyClass)) return createProxy(key,IProfile1D.class); else if (TH2.class.isAssignableFrom(keyClass)) return createProxy(key,IHistogram2D.class); else if (TH1.class.isAssignableFrom(keyClass)) return createProxy(key,IHistogram1D.class); else if (TTree.class.isAssignableFrom(keyClass)) return createProxy(key,ITuple.class); else return null; } private static IManagedObject createProxy(TKey key, Class proxyClass) { Class[] interfaces = { IManagedObject.class, proxyClass }; InvocationHandler handler = new MyInvocationHandler(key); return (IManagedObject) Proxy.newProxyInstance(Converter.class.getClassLoader(), interfaces, handler); } private static class MyInvocationHandler implements InvocationHandler { private TKey key; private IManagedObject backend; MyInvocationHandler(TKey key) { this.key = key; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); int nArgs = args == null ? 0 : args.length; if (nArgs ==0) { if ("name" .equals(methodName)) return key.getName(); if ("hashCode".equals(methodName)) return new Integer(key.hashCode()); if ("toString".equals(methodName)) return key.getName(); if ("type" .equals(methodName)) return ManagedObject.typeForClass(proxy.getClass()); } else if (nArgs == 1) { if ("equals" .equals(methodName)) return Boolean.valueOf(proxy == args[0]); } if (backend == null) { // System.out.println("Conversion of "+key.getName()+" caused by call to "+methodName); backend = internalConvert(key,key.getName()); } return method.invoke(backend,args); } } }