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
9 from ROOT
import TFile, TH1F
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:
16 http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/UserCode/CMG/CMGTools/H2TauTau/Colin/test_tauMu_2012_cfg.py?view=markup
18 THESE HISTOGRAMS MUST BE CONSISTENT, SEE
19 https://twiki.cern.ch/twiki/bin/view/CMS/CMGToolsPileUpReweighting#Generating_pile_up_distributions
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.
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!
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.
36 # build unweighted pu distribution using number of pile up interactions if False
37 # otherwise, use fill the distribution using number of true interactions
42 def __init__(self, cfg_ana, cfg_comp, looperName):
43 super(PileUpAnalyzer, self).
__init__(cfg_ana, cfg_comp, looperName)
47 if (hasattr(self.cfg_ana,
'makeHists'))
and (
not self.cfg_ana.makeHists):
50 self.
allVertices = self.cfg_ana.allVertices
if (hasattr(self.cfg_ana,
'allVertices'))
else "_AUTO_"
52 if self.cfg_comp.isMC
and self.
doHists:
57 if self.cfg_comp.isEmbed :
58 self.cfg_comp.puFileMC =
None
59 self.cfg_comp.puFileData =
None
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):
65 assert( os.path.isfile(os.path.expandvars(self.cfg_comp.puFileMC)) )
66 assert( os.path.isfile(os.path.expandvars(self.cfg_comp.puFileData)) )
68 self.
mcfile = TFile( self.cfg_comp.puFileMC )
69 self.
mchist = self.mcfile.Get(
'pileup')
70 self.mchist.Scale( 1 / self.mchist.Integral() )
72 self.
datafile = TFile( self.cfg_comp.puFileData )
74 self.datahist.Scale( 1 / self.datahist.Integral() )
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')
85 self.mchandles[
'pusi'] = AutoHandle(
86 'slimmedAddPileupInfo',
87 'std::vector<PileupSummaryInfo>',
88 fallbackLabel=
"addPileupInfo"
92 self.handles[
'vertices'] = AutoHandle(
"offlineSlimmedPrimaryVertices",
'std::vector<reco::Vertex>', fallbackLabel=
"offlinePrimaryVertices" )
94 self.handles[
'vertices'] = AutoHandle( self.
allVertices,
'std::vector<reco::Vertex>' )
97 super(PileUpAnalyzer,self).
beginLoop(setup)
98 self.averages.add(
'puWeight',
Average(
'puWeight') )
102 self.readCollections( event.input )
104 if self.cfg_comp.isEmbed :
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:
117 if self.cfg_ana.true
is False:
118 event.nPU = puInfo.nPU()
120 event.nPU = puInfo.nTrueInteractions()
123 self.rawmcpileup.hist.Fill( event.nPU )
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])
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)
141 bin = self.datahist.FindBin(event.nPU)
142 if bin<1
or bin>self.datahist.GetNbinsX():
145 data = self.datahist.GetBinContent(bin)
146 mc = self.mchist.GetBinContent(bin)
149 event.puWeight = data/mc
153 event.eventWeight *= event.puWeight
154 self.averages[
'puWeight'].
add( event.puWeight )
158 super(PileUpAnalyzer, self).
write(setup)
159 if self.cfg_comp.isMC
and self.
doHists:
160 self.rawmcpileup.write()
163 setattr(PileUpAnalyzer,
"defaultConfig", cfg.Analyzer(
164 class_object = PileUpAnalyzer,
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)