CMS 3D CMS Logo

PileUpAnalyzer.py
Go to the documentation of this file.
1 import os
2 from PhysicsTools.Heppy.analyzers.core.VertexHistograms import VertexHistograms
3 from PhysicsTools.Heppy.analyzers.core.Analyzer import Analyzer
4 from PhysicsTools.Heppy.analyzers.core.AutoHandle import AutoHandle
5 from PhysicsTools.HeppyCore.statistics.average import Average
6 from PhysicsTools.Heppy.physicsutils.PileUpSummaryInfo import PileUpSummaryInfo
7 import PhysicsTools.HeppyCore.framework.config as cfg
8 
9 from ROOT import TFile, TH1F
10 
11 class PileUpAnalyzer( Analyzer ):
12  '''Computes pile-up weights for MC from the pile up histograms for MC and data.
13  These histograms should be set on the components as
14  puFileData, puFileMC attributes, as is done here:
15 
16  http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/UserCode/CMG/CMGTools/H2TauTau/Colin/test_tauMu_2012_cfg.py?view=markup
17 
18  THESE HISTOGRAMS MUST BE CONSISTENT, SEE
19  https://twiki.cern.ch/twiki/bin/view/CMS/CMGToolsPileUpReweighting#Generating_pile_up_distributions
20 
21  If the component is not MC, or if the puFileData and puFileMC are not
22  set for the component, the reweighting is not done.
23 
24  The analyzer sets event.vertexWeight.
25  This weight is multiplied to the global event weight, event.eventWeight.
26  When using this analyzer, make sure that the VertexAnalyzer is disabled,
27  as you would be reweighting the MC PU distribution twice!
28 
29  Additionally, this analyzer writes in the output an histogram containing the unweighting MC
30  pile-up distribution, to be used in input of the weighting for a later pass.
31 
32  Example of use:
33 
34  puAna = cfg.Analyzer(
35  "PileUpAnalyzer",
36  # build unweighted pu distribution using number of pile up interactions if False
37  # otherwise, use fill the distribution using number of true interactions
38  true = True
39  )
40  '''
41 
42  def __init__(self, cfg_ana, cfg_comp, looperName):
43  super(PileUpAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName)
44 
45  self.doHists=True
46 
47  if (hasattr(self.cfg_ana,'makeHists')) and (not self.cfg_ana.makeHists):
48  self.doHists=False
49 
50  self.allVertices = self.cfg_ana.allVertices if (hasattr(self.cfg_ana,'allVertices')) else "_AUTO_"
51 
52  if self.cfg_comp.isMC and self.doHists:
53  self.rawmcpileup = VertexHistograms('/'.join([self.dirName,
54  'rawMCPU.root']))
55  self.enable = True
56  ## if component is embed return (has no trigger obj)
57  if self.cfg_comp.isEmbed :
58  self.cfg_comp.puFileMC = None
59  self.cfg_comp.puFileData = None
60 
61  if self.cfg_comp.isMC or self.cfg_comp.isEmbed:
62  if not hasattr(self.cfg_comp,"puFileMC") or (self.cfg_comp.puFileMC is None and self.cfg_comp.puFileData is None):
63  self.enable = False
64  else:
65  assert( os.path.isfile(os.path.expandvars(self.cfg_comp.puFileMC)) )
66  assert( os.path.isfile(os.path.expandvars(self.cfg_comp.puFileData)) )
67 
68  self.mcfile = TFile( self.cfg_comp.puFileMC )
69  self.mchist = self.mcfile.Get('pileup')
70  self.mchist.Scale( 1 / self.mchist.Integral() )
71 
72  self.datafile = TFile( self.cfg_comp.puFileData )
73  self.datahist = self.datafile.Get('pileup')
74  self.datahist.Scale( 1 / self.datahist.Integral() )
75  # import pdb; pdb.set_trace()
76  if self.mchist.GetNbinsX() != self.datahist.GetNbinsX():
77  raise ValueError('data and mc histograms must have the same number of bins')
78  if self.mchist.GetXaxis().GetXmin() != self.datahist.GetXaxis().GetXmin():
79  raise ValueError('data and mc histograms must have the same xmin')
80  if self.mchist.GetXaxis().GetXmax() != self.datahist.GetXaxis().GetXmax():
81  raise ValueError('data and mc histograms must have the same xmax')
82 
83  def declareHandles(self):
84  super(PileUpAnalyzer, self).declareHandles()
85  self.mchandles['pusi'] = AutoHandle(
86  'slimmedAddPileupInfo',
87  'std::vector<PileupSummaryInfo>',
88  fallbackLabel="addPileupInfo"
89  )
90 
91  if self.allVertices == '_AUTO_':
92  self.handles['vertices'] = AutoHandle( "offlineSlimmedPrimaryVertices", 'std::vector<reco::Vertex>', fallbackLabel="offlinePrimaryVertices" )
93  else:
94  self.handles['vertices'] = AutoHandle( self.allVertices, 'std::vector<reco::Vertex>' )
95 
96  def beginLoop(self, setup):
97  super(PileUpAnalyzer,self).beginLoop(setup)
98  self.averages.add('puWeight', Average('puWeight') )
99 
100 
101  def process(self, event):
102  self.readCollections( event.input )
103  ## if component is embed return (has no trigger obj)
104  if self.cfg_comp.isEmbed :
105  return True
106 
107  event.puWeight = 1
108  event.nPU = None
109  event.pileUpVertex_z = []
110  event.pileUpVertex_ptHat = []
111  if self.cfg_comp.isMC:
112  event.pileUpInfo = map( PileUpSummaryInfo,
113  self.mchandles['pusi'].product() )
114  for puInfo in event.pileUpInfo:
115  if puInfo.getBunchCrossing()==0:
116  # import pdb; pdb.set_trace()
117  if self.cfg_ana.true is False:
118  event.nPU = puInfo.nPU()
119  else:
120  event.nPU = puInfo.nTrueInteractions()
121 
122  if self.doHists:
123  self.rawmcpileup.hist.Fill( event.nPU )
124 
125  ##get z position of on-time pile-up sorted by pt-hat
126  ptHat_zPositions = zip(puInfo.getPU_pT_hats(),puInfo.getPU_zpositions())
127  ptHat_zPositions.sort(reverse=True)
128  for ptHat_zPosition in ptHat_zPositions:
129  event.pileUpVertex_z.append(ptHat_zPosition[1])
130  event.pileUpVertex_ptHat.append(ptHat_zPosition[0])
131 
132  if event.nPU is None:
133  raise ValueError('nPU cannot be None! means that no pu info has been found for bunch crossing 0.')
134  elif self.cfg_comp.isEmbed:
135  vertices = self.handles['vertices'].product()
136  event.nPU = len(vertices)
137  else:
138  return True
139 
140  if self.enable:
141  bin = self.datahist.FindBin(event.nPU)
142  if bin<1 or bin>self.datahist.GetNbinsX():
143  event.puWeight = 0
144  else:
145  data = self.datahist.GetBinContent(bin)
146  mc = self.mchist.GetBinContent(bin)
147  #Protect 0 division!!!!
148  if mc !=0.0:
149  event.puWeight = data/mc
150  else:
151  event.puWeight = 1
152 
153  event.eventWeight *= event.puWeight
154  self.averages['puWeight'].add( event.puWeight )
155  return True
156 
157  def write(self, setup):
158  super(PileUpAnalyzer, self).write(setup)
159  if self.cfg_comp.isMC and self.doHists:
160  self.rawmcpileup.write()
161 
162 
163 setattr(PileUpAnalyzer,"defaultConfig", cfg.Analyzer(
164  class_object = PileUpAnalyzer,
165  true = True, # use number of true interactions for reweighting
166  makeHists=False
167 )
168 )
169 
enable
if component is embed return (has no trigger obj)
OutputIterator zip(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp)
void add(std::map< std::string, TH1 * > &h, TH1 *hist)
static std::string join(char **cmd)
Definition: RemoteFile.cc:17
def __init__(self, cfg_ana, cfg_comp, looperName)