|
[Rivet-svn] r3279 - in branches/2011-07-aida2yoda: . binblackhole at projects.hepforge.org blackhole at projects.hepforge.orgFri Aug 5 14:29:15 BST 2011
Author: hoeth Date: Fri Aug 5 14:29:14 2011 New Revision: 3279 Log: merge r3260-r3262 from trunk, even though we will get rid of aida2root soon Modified: branches/2011-07-aida2yoda/ChangeLog branches/2011-07-aida2yoda/bin/aida2root branches/2011-07-aida2yoda/bin/rivet-mkhtml Modified: branches/2011-07-aida2yoda/ChangeLog ============================================================================== --- branches/2011-07-aida2yoda/ChangeLog Fri Aug 5 14:27:28 2011 (r3278) +++ branches/2011-07-aida2yoda/ChangeLog Fri Aug 5 14:29:14 2011 (r3279) @@ -1,3 +1,7 @@ +2011-07-29 Andy Buckley <andy at insectnation.org> + + * New version of aida2root from James Monk. + 2011-07-27 David Mallows <dave.mallows at gmail.com> * Updated MC_TTBAR.plot to reflect updated analysis. Modified: branches/2011-07-aida2yoda/bin/aida2root ============================================================================== --- branches/2011-07-aida2yoda/bin/aida2root Fri Aug 5 14:27:28 2011 (r3278) +++ branches/2011-07-aida2yoda/bin/aida2root Fri Aug 5 14:29:14 2011 (r3279) @@ -5,11 +5,11 @@ Verify in the ROOT user manual what needs to be setup for use of ROOT with python -E.g. do the following additional setup steps: +For example, additional setup steps such as this may be required: setup setenv PYTHONDIR /usr setenv PATH $ROOTSYS/bin:$PYTHONDIR/bin:$PATH - setenv LD_LIBRARY_PATH $ROOTSYS/lib:$PYTHONDIR/lib/python2.3:$LD_LIBRARY_PATH - setenv PYTHONPATH $ROOTSYS/lib:$PYTHONDIR/lib/python2.3 + setenv LD_LIBRARY_PATH $ROOTSYS/lib:$PYTHONDIR/lib/python2.6:$LD_LIBRARY_PATH + setenv PYTHONPATH $ROOTSYS/lib:$PYTHONDIR/lib/python2.6 """ import sys @@ -18,11 +18,10 @@ sys.exit(1) +import os, array -import os -from array import array try: - from ROOT import TGraphAsymmErrors, TFile + from ROOT import ROOT, TGraphAsymmErrors, TGraph2DErrors, TH1F, TH2F, TFile except: sys.stderr.write("Couldn't find PyROOT module. If ROOT is installed, PyROOT probably is too, but it's not currently accessible\n") foundpyroot = False @@ -40,160 +39,6 @@ sys.stderr.write("You can test if PyROOT is properly set up by calling 'import ROOT' at the interactive Python shell\n") sys.exit(1) - -## TODO: replace with lighthisto -class Histo: - def __init__(self): - self._bins = [] - self.path = None - self.name = None - self.title = None - - def __cmp__(self, other): - """Sort by $path/$name string""" - return self.fullPath() > other.fullPath() - - def __str__(self): - out = "Histogram '%s' with %d bins\n" % (self.fullPath(), self.numBins()) - out += "Title: %s\n" % self.title - out += "\n".join([str(b) for b in self.getBins()]) - return out - - def fullPath(self): - return os.path.join(self.path, self.name) - - def asFlat(self): - out = "### %s\n" % self.fullPath() - out += "## Title: %s\n" % self.title - out += "## Area: %s\n" % self.area() - out += "## Num bins: %d\n" % self.numBins() - out += "## xlow xhigh yval yerrminus yerrplus\n" - out += "\n".join([b.asFlat() for b in self.getBins()]) - return out - - def asRoot(self): - xerrminus = array('f',self.numBins()*[0.]) - xerrplus = array('f',self.numBins()*[0.]) - xval = array('f',self.numBins()*[0.]) - yval = array('f',self.numBins()*[0.]) - yerrminus = array('f',self.numBins()*[0.]) - yerrplus= array('f',self.numBins()*[0.]) - ibin = 0 - for b in self.getBins(): - xval[ibin] = b.getXval() - yval[ibin] = b.getYval() - xerrminus[ibin], xerrplus[ibin] = b.getXErrors() - yerrminus[ibin], yerrplus[ibin] = b.getYErrors() - #print 'xerrminus=',xerrminus[ibin],' xerrplus=',xerrplus[ibin],' xval=',xval[ibin],' yval=',yval[ibin],' yerrplus=',yerrplus[ibin],' yerrminus=',yerrminus[ibin] - ibin = ibin +1 - tg = TGraphAsymmErrors(self.numBins(), xval, yval, xerrminus, xerrplus, yerrminus, yerrplus); - tg.SetTitle(self.title); - tg.SetName(self.name.replace("-", "_")); - return tg - - def numBins(self): - return len(self._bins) - - def getBins(self): - return sorted(self._bins) - - def setBins(self, bins): - self._bins = bins - return self - - def addBin(self, bin): - self._bins.append(bin) - return self - - def getBin(self, index): - self._bins.sort() - return self.getBins()[index] - - bins = property(getBins, setBins) - - def area(self): - return sum([bin.area() for bin in self.bins]) - - def __iter__(self): - return iter(self.getBins()) - - def __len__(self): - return len(self._bins) - - def __getitem__(self, index): - return self.getBin(index) - - -## TODO: replace with lighthisto -class Bin: - """A simple container for a binned value with an error.""" - def __init__(self, xval=0, xerrminus=None, xerrplus=None, yval=0, yerrminus=0, yerrplus=0, focus=None): - self.xval = xval - self.xerrplus = xerrplus - self.xerrminus= xerrminus - self.yval = yval - self.yerrplus = yerrplus - self.yerrminus = yerrminus - self.focus= focus - - def __str__(self): - out = "%e to %e: %e +- %e" % (self.xval-self.xerrminus, self.xval+self.xerrplus, self._yval, self._yerr) - return out - - def asFlat(self): - out = "%e %e %e %e %e" % (self.xval-self.xerrminus, self.xval+self.xerrplus, self.yval, self.yerrminus, self.yerrplus) - return out - - def __cmp__(self, other): - """Sort by mean x value (yeah, I know...)""" - return (self.xval) > (other.xval) - - def getXRange(self): - return (self.xval-self.xerrminus, self.xval+self.xerrplus) - - def getXErrors(self): - return (self.xerrminus, self.xerrplus) - - def setXRange(self, xlow, xhigh): - self.xlow = xlow - self.xhigh = xhigh - return self - - def getYErrors(self): - return (self.yerrminus, self.yerrplus) - - def getBinCenter(self): - """Geometric middle of the bin range.""" - return self.xlow + .5*(self.xhigh - self.xlow) - - def getFocus(self): - """Mean x-value of the bin.""" - if self.focus is not None: - return (self.xlow + self.xhigh)/2.0 - else: - return self.focus - - def getXval(self): - return self.xval - - def getYval(self): - return self.yval - - def area(self): - return self.yval * (self.xerrplus - self.xerrminus) - - def getYErr(self): - """Get mean of +ve and -ve y-errors.""" - return (self.yerrplus + self.yerrminus)/2.0 - - def setYErr(self, yerr): - """Set both +ve and -ve y-errors simultaneously.""" - self.yerrplus = yerr - self.yerrminus = yerr - return self - - - ## Try to load faster but non-standard cElementTree module try: import xml.etree.cElementTree as ET @@ -208,33 +53,285 @@ sys.exit(1) +class Histo: + + def __init__(self, nDim): + self._points = [] + self.name = "" + self.title = "" + self._nDim = nDim + + def addPoint(self, dp): + if dp.dimensionality() != self._nDim: + er = "Tried to add a datapoint of dimensionality " + str(dp.dimensionality()) + " to a histogram of dimensionality " + str(self._nDim) + sys.stderr.write(er) + sys.exit(1) + self._points.append(dp) + + def numPts(self): + return len(self._points) + + def asTGraph(self): + tg = TGraph() + tg.SetName(self.name) + tg.SetTitle(self.title) + return tg + + def asHisto(self): + tg = self.asTGraph() + histo = tg.Histogram().Clone() + return histo + + @staticmethod + def equalFloats(left, right, precision=1.e-6): + + try: + test = abs((left - right) / (left + right)) + return test < precision + except ZeroDivisionError: + if left * right < 0.: + return False + else: + return True + + return False + + +class Histo2D(Histo): + + def __init__(self): + Histo.__init__(self,3) + + def asTGraph(self): + xs = array.array("d", []) + ex = array.array("d", []) + ys = array.array("d", []) + ey = array.array("d", []) + zs = array.array("d", []) + ez = array.array("d", []) + + for pt in self._points: + x = pt.mean(0) + erx = pt.er(0) + y = pt.mean(1) + ery = pt.er(1) + z = pt.mean(2) + erz = pt.er(2) + + xs.append(x) + ex.append(erx) + ys.append(y) + ey.append(ery) + zs.append(z) + ez.append(erz) + + if self.numPts() == 0: + tg = TGraph2DErrors() + er = "Tried to create TGraph2DErrors called " + self.name + " with zero datapoints" + else: + tg = TGraph2DErrors(self.numPts(), xs, ys, zs, ex, ey, ez) + tg.SetTitle(self.title) + tg.SetName(self.name.replace("-", "_")) + return tg + + def asTHisto(self): + + if self.numPts() == 0: + histo = TH2F() + histo.SetName(self.name) + return histo + + tmpXEdges = [] + tmpYEdges = [] + + for pt in self._points: + tmpXEdges.append(pt.lowEdge(0)) + tmpXEdges.append(pt.highEdge(0)) + tmpYEdges.append(pt.lowEdge(1)) + tmpYEdges.append(pt.highEdge(1)) + + sortedX = sorted(tmpXEdges) + sortedY = sorted(tmpYEdges) + + xBinEdges = array.array("d", [sortedX[0]]) + yBinEdges = array.array("d", [sortedY[0]]) + + for edge in sortedX: + if not Histo.equalFloats(edge, xBinEdges[-1]): + xBinEdges.append(edge) + + for edge in sortedY: + if not Histo.equalFloats(edge, yBinEdges[-1]): + yBinEdges.append(edge) + + histo = TH2F(self.name, self.title, len(xBinEdges)-1, xBinEdges, len(yBinEdges)-1, yBinEdges) + histo.Sumw2() + + for pt in self._points: + bin = histo.FindBin(pt.value(0), pt.value(1)) + histo.SetBinContent(bin, pt.value(2)) + histo.SetBinError(bin, pt.er(2)) + + return histo + + +class Histo1D(Histo): + def __init__(self): + Histo.__init__(self,2) + + def asTGraph(self): + xerrminus = array.array("d", []) + xerrplus = array.array("d", []) + xval = array.array("d", []) + yval = array.array("d", []) + yerrminus = array.array("d", []) + yerrplus = array.array("d", []) + + for pt in self._points: + x = pt.value(0) + xplus = pt.erUp(0) + xminus = pt.erDn(0) + + y = pt.value(1) + yplus = pt.erUp(1) + yminus = pt.erDn(1) + + xval.append(x) + xerrminus.append(xminus) + xerrplus.append(xplus) + yval.append(y) + yerrminus.append(yminus) + yerrplus.append(yplus) + + tg = TGraphAsymmErrors(self.numPts(), xval, yval, xerrminus, xerrplus, yerrminus, yerrplus) + tg.SetTitle(self.title) + tg.SetName(self.name.replace("-", "_")) + return tg + + def asTHisto(self): + + if self.numPts() == 0: + histo = TH1F() + histo.SetName(self.name) + return histo + + binEdges = array.array("d", []) + binEdges.append(self._points[0].lowEdge(0)) + + bin = 0 + binNumbers = [] + + for pt in self._points: + lowEdge = pt.lowEdge(0) + highEdge = pt.highEdge(0) + if not Histo1D.equalFloats(lowEdge, binEdges[-1]): + binEdges.append(lowEdge) + bin = bin + 1 + + bin = bin + 1 + binEdges.append(highEdge) + binNumbers.append(bin) + + histo = TH1F(self.name, self.title, self.numPts(), binEdges) + histo.Sumw2() + + for i, pt in enumerate(self._points): + histo.SetBinContent(binNumbers[i], pt.value(1)) + histo.SetBinError(binNumbers[i], pt.er(1)) + + return histo + + +class DataPoint: + + def __init__(self): + self._dims = 0 + self._coords = [] + self._erUps = [] + self._erDns = [] + + def setCoord(self, val, up, down): + self._dims = self._dims + 1 + self._coords.append(val) + self._erUps.append(up) + self._erDns.append(down) + + def dimensionality(self): + return self._dims + + def th(self, dim): + th = "th" + if dim == 1: + th = "st" + elif dim == 2: + th = "nd" + elif dim == 3: + th = "rd" + return th + + def checkDimensionality(self, dim): + if dim >= self.dimensionality(): + er = "Tried to obtain the " + str(dim) + self.th(dim) + " dimension of a " + str(self.dimensionality()) + " dimension DataPoint" + sys.stderr.write(er) + sys.exit(1) + + def value(self, dim): + self.checkDimensionality(dim) + return self._coords[dim] + + def erUp(self, dim): + self.checkDimensionality(dim) + return self._erUps[dim] + + def erDn(self, dim): + self.checkDimensionality(dim) + return self._erDns[dim] + + def mean(self, dim): + val = self.value(dim) + 0.5 * (self.erUp(dim) - self.erDn(dim)) + return val + + def er(self, dim): + ee = 0.5 * (self.erUp(dim) + self.erDn(dim)) + return ee + + def lowEdge(self, dim): + return self.value(dim) - self.erDn(dim) + + def highEdge(self, dim): + return self.value(dim) + self.erUp(dim) + def mkHistoFromDPS(dps): - """Make a mini histo representation from an AIDA dataPointSet tag.""" - myhist = Histo() - myhist.name = dps.get("name") - myhist.title = dps.get("title") - myhist.path = dps.get("path") - points = dps.findall("dataPoint") - numbins = len(points) - for binnum, point in enumerate(points): - bin = Bin() - for d, m in enumerate(point.findall("measurement")): - val = float(m.get("value")) - down = float(m.get("errorMinus")) - up = float(m.get("errorPlus")) - if d == 0: - low = val - down - high = val + up - bin.setXRange(low, high) - bin.xval = val - bin.xerrplus = up - bin.xerrminus = down - elif d == 1: - bin.yval = val - bin.yerrplus = up - bin.yerrminus = down - myhist.addBin(bin) - return myhist + + dim = dps.get("dimension") + + is3D = False + if dim == "3": + myhist = Histo2D() + is3D = True + else: + myhist = Histo1D() + + myhist.name = dps.get("name") + myhist.title = dps.get("title") + myhist.path = dps.get("path") + + points = dps.findall("dataPoint") + numbins = len(points) + + for ptNum, point in enumerate(points): + dp = DataPoint() + for d, m in enumerate(point.findall("measurement")): + val = float(m.get("value")) + down = float(m.get("errorMinus")) + up = float(m.get("errorPlus")) + dp.setCoord(val, up, down) + myhist.addPoint(dp) + + return myhist + + +################################## from optparse import OptionParser @@ -245,6 +342,13 @@ parser.add_option("-m", "--match", action="append", help="Only write out histograms whose $path/$name string matches these regexes", dest="PATHPATTERNS") +parser.add_option("-g", "--tgraph", action="store_true", default=True, + help="Store output as ROOT TGraphAsymmErrors or TGraph2DErrors", + dest="TGRAPH") +parser.add_option("-t", "--thisto", action="store_false", + help="Store output as ROOT TH1 or TH2", + dest="TGRAPH") + opts, args = parser.parse_args() if opts.PATHPATTERNS is None: opts.PATHPATTERNS = [] @@ -253,11 +357,11 @@ sys.stderr.write("Must specify at least one AIDA histogram file\n") sys.exit(1) -import re for aidafile in args: - out = sys.stdout + tree = ET.parse(aidafile) histos = [] + for dps in tree.findall("dataPointSet"): useThisDps = True if len(opts.PATHPATTERNS) > 0: @@ -268,13 +372,17 @@ useThisDps = True break if useThisDps: - histos.append(mkHistoFromDPS(dps)) + histos.append(mkHistoFromDPS(dps)) if len(histos) > 0: if opts.SMARTOUTPUT: outfile = os.path.basename(aidafile).replace(".aida", ".root") out = TFile(outfile,"RECREATE") for h in sorted(histos): - h.asRoot().Write() + if opts.TGRAPH: + h.asTGraph().Write() + else: + h.asTHisto().Write() + out.Close() else: sys.stderr.write("ROOT objects must be written to a file") Modified: branches/2011-07-aida2yoda/bin/rivet-mkhtml ============================================================================== --- branches/2011-07-aida2yoda/bin/rivet-mkhtml Fri Aug 5 14:27:28 2011 (r3278) +++ branches/2011-07-aida2yoda/bin/rivet-mkhtml Fri Aug 5 14:29:14 2011 (r3279) @@ -57,7 +57,7 @@ default=False, help="ignore unvalidated analyses.") parser.add_option("-m", "--match", action="append", dest="PATHPATTERNS", help="only write out histograms from analyses whose name matches any of these regexes") -parser.add_option("-M", "--unmatch", action="append", dest="PATHUNPATTERNS" +parser.add_option("-M", "--unmatch", action="append", dest="PATHUNPATTERNS", help="Exclude histograms whose $path/$name string matches these regexes") parser.add_option("-v", "--verbose", help="Add extra debug messages", dest="VERBOSE", action="store_true", default=False)
More information about the Rivet-svn mailing list |