source: HiSusy/trunk/Delphes/Delphes-3.0.9/python/DelphesAnalysis/ControlPlots.py @ 5

Last change on this file since 5 was 5, checked in by zerwas, 11 years ago

update to Delphes-3.0.9

File size: 7.6 KB
Line 
1#!/usr/bin/env python
2
3#######################################################################################
4###  Option parsing and main routine  #################################################
5#######################################################################################
6
7from optparse import OptionParser
8import sys
9import os
10usage="""%prog [options]"""
11description="""A simple script to generate control plots."""
12epilog="""Example:
13./ControlPlots.py -i ./ -o controlPlots_demo.root --all
14"""
15parser = OptionParser(usage=usage,add_help_option=True,description=description,epilog=epilog)
16parser.add_option("-c", "--conf", dest="conf", default=None,
17                  help="Configuration file.")
18parser.add_option("-i", "--inputPath", dest="path",
19                  help="Read input file from DIR.", metavar="DIR")
20parser.add_option("-o", "--output", dest='outputname', default=None,
21                  help="Save output as FILE.", metavar="FILE")
22parser.add_option("--all",action="store_true",dest="all",
23                  help="Process all levels.")
24parser.add_option("-l", "--level", dest="levels",
25                  help="Specify a coma-separated list of levels to be processed. No space is allowed.")
26parser.add_option("--Njobs", type="int", dest='Njobs', default="1",
27                  help="Number of jobs when splitting the processing.")
28parser.add_option("--jobNumber", type="int", dest='jobNumber', default="0",
29                  help="Number of the job is a splitted set of jobs.")
30
31(options, args) = parser.parse_args()
32
33#special treatment of the config file... the rest of the options will be parsed in main.
34if options.conf is not None:
35  try:
36    theUserConf = __import__(os.path.splitext(options.conf)[0])
37  except:
38    raise ImportError("%s is not a valid configuration file."%options.conf)
39  else:
40    os.environ["DelphesAnalysisCfg"]=options.conf
41from CPconfig import configuration
42if options.outputname is None:
43  options.outputname = configuration.defaultFilename+".root"
44
45import Delphes
46import ROOT
47import itertools
48import time
49from importlib import import_module
50from AnalysisEvent import AnalysisEvent
51from BaseControlPlots import getArgSet
52import EventSelection
53import cProfile
54
55def main(options):
56  """simplistic program main"""
57  # do basic arg checking
58  if options.path is None: 
59    print "Error: no input path specified."
60    parser.print_help()
61    return
62  levels = []
63  if options.all:
64    levels = range(EventSelection.eventCategories())
65  elif not options.levels is None:
66    levels= map(int,options.levels.split(','))
67  levels.sort()
68  if len(levels)==0:
69    print "Error: no level specified for processing."
70    parser.print_help()
71    return
72  if min(levels)<0:
73    print "Error: levels must be positive integers."
74    parser.print_help()
75    return
76  if max(levels)>=EventSelection.eventCategories():
77    print "Error: last level is",EventSelection.eventCategories()-1
78    parser.print_help()
79    return
80  if options.Njobs<1:
81    print "Error: Njobs must be strictly positive."
82    parser.print_help()
83    return
84  if options.jobNumber>=options.Njobs:
85    print "Error: jobNumber must be strictly smaller than Njobs."
86    parser.print_help()
87    return
88  # if all ok, run the procedure
89  runAnalysis(path=options.path,outputname=options.outputname, levels=levels, Njobs=options.Njobs, jobNumber=options.jobNumber)
90
91#######################################################################################
92### Central Routine: manage input/output, loop on events, manage weights and plots  ###
93#######################################################################################
94
95def runAnalysis(path, levels, outputname="controlPlots.root", Njobs=1, jobNumber=1):
96  """produce all the plots in one go"""
97
98  # inputs
99  if os.path.isdir(path):
100    dirList=list(itertools.islice(os.listdir(path), jobNumber, None, Njobs))
101    files=[]
102    for fname in dirList:
103      files.append(path+"/"+fname)
104  elif os.path.isfile(path):
105    files=[path]
106  else:
107    files=[]
108
109  # output
110  output = ROOT.TFile(outputname, "RECREATE")
111  if configuration.runningMode=="dataset":
112    ROOT.RooAbsData.setDefaultStorageType(ROOT.RooAbsData.Tree)
113    rds = ROOT.RooDataSet(configuration.RDSname, configuration.RDSname, ROOT.RooArgSet())
114
115  # events iterator, plus configuration of standard collections and producers
116  events = AnalysisEvent(files)
117  EventSelection.prepareAnalysisEvent(events)
118
119  # prepare the plots
120  controlPlots=[]
121  if configuration.runningMode=="plots":
122    leafList = [None]*EventSelection.eventCategories()
123    createDirectory(EventSelection.categoriesHierarchy(), output, leafList)
124    for levelDir in leafList:
125      levelPlots=[]
126      for cp in configuration.controlPlots:
127        levelPlots.append(getattr(import_module(cp.module),cp.classname)(dir=levelDir.mkdir(cp.label),mode="plots"))
128      controlPlots.append(levelPlots)
129  else:
130    for cp in configuration.controlPlots:
131      controlPlots.append(getattr(import_module(cp.module),cp.classname)(dir=None, mode="dataset", dataset=rds))
132
133  # book histograms (separate iteration for clarity)
134  if configuration.runningMode=="plots":
135    for level in levels:
136     for conf,cp in zip(configuration.controlPlots,controlPlots[level]):
137       cp.beginJob(**conf.kwargs)
138  else:
139    for conf,cp in zip(configuration.controlPlots,controlPlots):
140      cp.beginJob(**conf.kwargs)
141    for cp in controlPlots[:1]:
142      cp.defineCategories(EventSelection.categoryNames)
143
144  # process events
145  i = 0
146  t0 = time.time()
147  for event in events:
148    # printout
149    if i%100==0 : 
150      print "Processing... event %d. Last batch in %f s." % (i,(time.time()-t0))
151      t0 = time.time()
152    if configuration.runningMode=="plots":
153      # loop on channels
154      plots = filter(lambda x: EventSelection.isInCategory(x,event.category) ,levels)
155      # process the event once (for the first level)
156      selectionPlotsData=[]
157      for level in plots[:1]:
158        for cp in controlPlots[level]:
159          selectionPlotsData.append(cp.process(event))
160      # fill the histograms
161      for level in plots:
162        for cp, data in zip(controlPlots[level],selectionPlotsData):
163          cp.fill(data, event.weight(category=level))
164    else:
165      for cp in controlPlots[:1]:
166        # set categories (first CP only)
167        cp.setCategories(map(lambda c:EventSelection.isInCategory(c, event.category),range(EventSelection.eventCategories())))
168      for cp in controlPlots:
169        # process event (all CP)
170        cp.processEvent(event)
171      # add to the dataset
172      rds.add(getArgSet(controlPlots))
173    i += 1
174
175  # save all
176  if configuration.runningMode=="plots":
177    for level in levels:
178     for cp in controlPlots[level]: 
179       cp.endJob()
180  else:
181   for cp in controlPlots: 
182     cp.endJob()
183
184  # for dataset, write the merged RDS to file
185  if configuration.runningMode=="dataset":
186    output.cd()
187    ws_ras = ROOT.RooWorkspace(configuration.WSname, configuration.WSname)
188    getattr(ws_ras,'import')(rds.get())
189    output.Add(ws_ras)
190    ws_ras.Write()
191    rds.tree().Write()
192 
193  # close the file
194  output.Close()
195
196def createDirectory(dirStructure, directory, leafList):
197  """Recursively creates the directories for the various stages"""
198  for key,item in dirStructure.iteritems():
199    if isinstance(item, dict):
200      createDirectory(item, directory.mkdir(key), leafList)
201    else:
202      leafList[item]=directory.mkdir("stage_"+str(item),key)
203
204#######################################################################################
205### Program bootstrap  ################################################################
206#######################################################################################
207
208if __name__ == "__main__":
209  main(options)
210  #cProfile.run('main(options)', 'controlPlots.prof')
211
Note: See TracBrowser for help on using the repository browser.