CMS 3D CMS Logo

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