|
[Rivet-svn] r2196 - trunk/binblackhole at projects.hepforge.org blackhole at projects.hepforge.orgThu Dec 17 14:36:00 GMT 2009
Author: holsch Date: Thu Dec 17 14:36:00 2009 New Revision: 2196 Log: Changing name of normalisation script Added: trunk/bin/rivet-normalise-histos (contents, props changed) Deleted: trunk/bin/normalise-to-refdata Modified: trunk/bin/Makefile.am Modified: trunk/bin/Makefile.am ============================================================================== --- trunk/bin/Makefile.am Thu Dec 17 14:34:10 2009 (r2195) +++ trunk/bin/Makefile.am Thu Dec 17 14:36:00 2009 (r2196) @@ -1,5 +1,5 @@ bin_SCRIPTS = rivet-config rivet-buildplugin -dist_bin_SCRIPTS = aida2flat aida2root compare-histos make-html make-plots rivet-mkanalysis chop_bins normalise-to-refdata +dist_bin_SCRIPTS = aida2flat aida2root compare-histos make-html make-plots rivet-mkanalysis chop_bins rivet-normalise-histos EXTRA_DIST = flat2aida if ENABLE_PYEXT Added: trunk/bin/rivet-normalise-histos ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/bin/rivet-normalise-histos Thu Dec 17 14:36:00 2009 (r2196) @@ -0,0 +1,275 @@ +#!/usr/bin/env python + +"""%prog -r <REFDATAPATH> -O <observable-file> <AIDAFILE> + +Normalise histos in observable-file of AIDAFILE to the area of the +corresponding histos in REFAIDAPATH. REFAIDAPATH can either be +a single AIDA-file or a directory containing AIDA-files. + +Or, if no REFAIDAPATH is given, normalise to new area given in +observable-file "observables_and_areas", e.g.: +CDF_2000_S4155203_d01-x01-y01 1.0 + +You can also define bin to chop out in the observable-file in the +same way as in chop_bins: +CDF_2000_S4155203_d01-x01-y01:0:35 1.0 +This will chop the bins with Z-pT > 35 GeV and afterwards perform +the renormalisation. + + +Example: + %prog -r /usr/share/Rivet/ -O observables out.aida +This will return the Z-boson pT-distribution, normalised to the histo-area +measured by CDF. + %prog -O observables_and_areas out.aida +This will return the Z-boson pT-distribution, normalised to 1.0 + +""" + +import os, re, sys, logging +from lighthisto import Histo +## Make "sorted" a builtin function on Python < 2.4 +if not 'sorted' in dir(__builtins__): + def sorted(iterable, cmp=None, key=None, reverse=None): + rtn = iterable + rtn.sort(cmp) + return rtn + +## Add logging.log if needed +if not 'log' in dir(logging): + def _logit(level, msg): + l = logging.getLogger() + l.log(level, msg) + logging.log = _logit + +try: + from IPython.Shell import IPShellEmbed + ipshell = IPShellEmbed([]) +except: + logging.info("Ipython shell not available.") + + +## Try to load faster but non-standard cElementTree module +try: + import xml.etree.cElementTree as ET +except ImportError: + try: + import cElementTree as ET + except ImportError: + try: + import xml.etree.ElementTree as ET + except: + sys.stderr.write("Can't load the ElementTree XML parser: please install it!\n") + sys.exit(1) + + +def getHistosFromAIDA(aidafile): + '''Get a dictionary of histograms indexed by name.''' + if not re.match(r'.*\.aida$', aidafile): + logging.error("Error: input file '%s' is not an AIDA file" % aidafile) + sys.exit(2) + aidafilepath = os.path.abspath(aidafile) + if not os.access(aidafilepath, os.R_OK): + logging.error("Error: cannot read from %s" % aidafile) + sys.exit(2) + + histos = {} + tree = ET.parse(aidafilepath) + for dps in tree.findall("dataPointSet"): + ## Get this histogram's path name + dpsname = os.path.join(dps.get("path"), dps.get("name")) + ## Is it a data histo? + h = Histo.fromDPS(dps) + h.isdata = dpsname.upper().startswith("/REF") + if h.isdata: + dpsname = dpsname.replace("/REF", "") + histos[dpsname] = h + return histos + +def getRefHistos(refpath): + """ Return dictionary of reference histos {name: histo}. + Refpath can either be a single file or a directory. + """ + refhistos = {} + if not refpath is None: + try: + refhistos=getHistosFromAIDA(refpath) + except: + for aida in os.listdir(refpath): + if aida.endswith(".aida"): + temp = getHistosFromAIDA(os.path.join(refpath, aida)) + for k, v in temp.iteritems(): + if not k in refhistos.keys(): + refhistos[k]=v + return refhistos + +def readObservableFile(obsfile): + """ Read observables to normalise from file obsfile. + Return-values are a list of the histo-names to normalise and a + dictionary with name:newarea entries. + """ + obslist = [] + obsnorms = {} + bindefs = {} + + if obsfile is not None: + try: + f = open(obsfile, 'r') + except: + logging.error("Cannot open histo list file %s" % opts.obsfile) + sys.exit(2) + for line in f: + stripped = line.strip() + # Skip empty or commented lines + if len(stripped) == 0 or stripped.startswith("#"): + continue + + # Split the line to find out whether newarea is given in obsfile + splitline = stripped.split() + + # Try to read bin specs for chopping + try: + path, low, high = splitline[0].split(":") + except: + path = splitline[0].split(":")[0] + low = "" + high = "" + logging.warning("No bin definition given for %s" % (line)) + #sys.exit(1) + if low == "": + low = None + else: + low = float(low) + if high == "": + high = None + else: + high = float(high) + bindefs[path] = (low, high) + + # Try to read areas to normalise to from obsfile + if len(splitline) == 2: + obsnorms[path] = float(splitline[1]) + obslist.append(path) + f.close() + return obslist, obsnorms, bindefs + + +if __name__ == "__main__": + from optparse import OptionParser, OptionGroup + parser = OptionParser(usage=__doc__) + + parser.add_option("-O", "--obsfile", default=None, + help="Specify a file with histograms (and bin ranges) " + + " that are to be normalised.") + parser.add_option("-r", "--refdir", default=None, + help="File of folder with reference histos") + parser.add_option("-o", "--outdir", + dest="outdir", default="renormalised", + help="output directory (default: %default)") + parser.add_option("-a", dest="AIDA", default=True, action="store_true", + help="Produce AIDA output rather than FLAT") + parser.add_option("-f", dest="AIDA", action="store_false", + help="Produce FLAT output rather than AIDA") + verbgroup = OptionGroup(parser, "Verbosity control") + verbgroup.add_option("-V", "--verbose", action="store_const", + const=logging.DEBUG, dest="LOGLEVEL", + help="print debug (very verbose) messages") + verbgroup.add_option("-Q", "--quiet", action="store_const", + const=logging.WARNING, dest="LOGLEVEL", + help="be very quiet") + parser.set_defaults(bins=[], + outdir=".", + LOGLEVEL=logging.INFO) + opts, args = parser.parse_args() + + + # Configure logging + try: + logging.basicConfig(level=opts.LOGLEVEL, format="%(message)s") + except: + pass + h = logging.StreamHandler() + h.setFormatter(logging.Formatter("%(message)s")) + logging.getLogger().setLevel(opts.LOGLEVEL) + if logging.getLogger().handlers: + logging.getLogger().handlers[0] = h + else: + logging.getLogger().addHandler(h) + + + + # Read in histogram files to normalise + histos = getHistosFromAIDA(args[0]) + + # Read in reference histos to get reference areas to normalise to + refhistos = getRefHistos(opts.refdir) + + # Read in observables, if no observable file is given or observable file + # is empty all observables will be renormalised if possible + obslist, obsnorms, bindefs = readObservableFile(opts.obsfile) + if len(obslist) == 0: + logging.warning("No observable file given or empty, will try to ", + "normalise all histos.") + obslist = histos.keys() + + + # Create output filename + base = args[0].split("/")[-1].split(".aida")[0] + if opts.AIDA: + outfile = os.path.join(opts.outdir, base + "-renormed.aida") + else: + outfile = os.path.join(opts.outdir, base + "-renormed.dat") + if not os.path.exists(opts.outdir): + logging.info("Creating outdir %s"%opts.outdir) + os.mkdir(opts.outdir) + + aidaheader = """<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE aida SYSTEM "http://aida.freehep.org/schemas/3.3/aida.dtd"> +<aida version="3.3"> + <implementation version="1.1" package="FreeHEP"/> + """ + # Open file for output + f = open(outfile, "w") + if opts.AIDA: + f.write(aidaheader) + + + # Iterate over all histos + for name, histo in histos.iteritems(): + # Find out whether ref-histo is given + if name in refhistos.keys(): + tempref = refhistos[name] + else: + tempref = histos[name] + + # Try to chop bins + if name in bindefs.keys(): + tempref = tempref.chop(bindefs[name]) + tempold = histos[name].chop(bindefs[name]) + else: + #tempref = refhistos[name] + tempold = histos[name] + + # Get old and new histogram areas + oldarea = tempold.getArea() + if name in obsnorms.keys(): + newarea = obsnorms[name] + else: + newarea = tempref.getArea() + + # Renormalise histo + logging.info("Renormalising %s from %f to %f"%(name, oldarea, + newarea)) + renormed = tempold.renormalise(newarea) + + # Write to file + if opts.AIDA: + f.write(renormed.asAIDA()) + else: + f.write(renormed.asFlat()) + + + if opts.AIDA: + f.write("</aida>") + + logging.info("Done. Written output to %s."%outfile)
More information about the Rivet-svn mailing list |