1 |
#include "TrkUpgradeAnalysis/VHbb/interface/CutSetPlotSet.h"
|
2 |
|
3 |
#include <stdexcept>
|
4 |
#include <sstream>
|
5 |
|
6 |
#include <TDirectory.h>
|
7 |
#include <TH1F.h>
|
8 |
#include <TTree.h>
|
9 |
|
10 |
#include "TrkUpgradeAnalysis/VHbb/interface/IBasicCut.h"
|
11 |
#include "TrkUpgradeAnalysis/VHbb/interface/IHistogramVariable.h"
|
12 |
#include "TrkUpgradeAnalysis/VHbb/interface/tools.h" // required for NTupleRow
|
13 |
|
14 |
#include "VHbbAnalysis/VHbbDataFormats/interface/VHbbCandidate.h"
|
15 |
|
16 |
#include <iostream>
|
17 |
|
18 |
trkupgradeanalysis::CutSetPlotSet::CutSetPlotSet( boost::shared_ptr<trkupgradeanalysis::VHbbCandidateCutSet> pCutSet, bool createNTupleOfAdditionalVariables )
|
19 |
: histogramHaveBeenBooked_(false), pCutSet_(pCutSet), createNTupleOfAdditionalVariables_(createNTupleOfAdditionalVariables), pAdditionalVariableTree_(NULL)
|
20 |
{
|
21 |
// No operation besides the initialiser list.
|
22 |
}
|
23 |
|
24 |
void trkupgradeanalysis::CutSetPlotSet::book( TDirectory* pDirectory )
|
25 |
{
|
26 |
if( histogramHaveBeenBooked_ ) throw std::runtime_error( "trkupgradeanalysis::CutSetPlotSet::book() - histograms have already been booked" );
|
27 |
|
28 |
//
|
29 |
// Note that the root file which TDirectory is part of takes ownership of all
|
30 |
// of these objects, so I don't need to (and shouldn't) delete them when I'm
|
31 |
// finished.
|
32 |
//
|
33 |
|
34 |
passedCandidateHistograms_.book( pDirectory );
|
35 |
|
36 |
size_t numberOfCuts=pCutSet_->numberOfCuts();
|
37 |
|
38 |
pCutsPassed_=new TH1F( "cutsPassed","Events passing each cut",numberOfCuts+1,-0.5,numberOfCuts+0.5);
|
39 |
pCutsPassed_->SetDirectory(pDirectory);
|
40 |
pCutsPassed_->GetXaxis()->SetBinLabel( 1, "Input VHbbCandidates" );
|
41 |
|
42 |
pCutFlow_=new TH1F( "cutFlow","Events passing all cuts",numberOfCuts+1,-0.5,numberOfCuts+0.5);
|
43 |
pCutFlow_->SetDirectory(pDirectory);
|
44 |
pCutFlow_->GetXaxis()->SetBinLabel( 1, "Input VHbbCandidates" );
|
45 |
|
46 |
// Create a directory for the variables for all candidates
|
47 |
TDirectory* pAllCandidatesDirectory=pDirectory->GetDirectory( "AllCandidates" );
|
48 |
if( pAllCandidatesDirectory==NULL ) pAllCandidatesDirectory=pDirectory->mkdir( "AllCandidates" );
|
49 |
|
50 |
// Create a directory for the variables for all candidates that pass the cuts
|
51 |
TDirectory* pPassedCandidatesDirectory=pDirectory->GetDirectory( "PassedCandidates" );
|
52 |
if( pPassedCandidatesDirectory==NULL ) pPassedCandidatesDirectory=pDirectory->mkdir( "PassedCandidates" );
|
53 |
|
54 |
// Create a directory for the N-1 plots
|
55 |
TDirectory* pNMinus1Directory=pDirectory->GetDirectory( "N-1_Plots" );
|
56 |
if( pNMinus1Directory==NULL ) pNMinus1Directory=pDirectory->mkdir( "N-1_Plots" );
|
57 |
|
58 |
std::stringstream nameStream;
|
59 |
for( size_t a=0; a<numberOfCuts; ++a )
|
60 |
{
|
61 |
const trkupgradeanalysis::IBasicCut& cut=pCutSet_->cutAt(a);
|
62 |
const trkupgradeanalysis::IHistogramVariable& cutVariable=cut.cutVariable();
|
63 |
|
64 |
std::string cutName=cut.name();
|
65 |
// The bin numbering is "a+2" here because root bin numbering starts at 1, and
|
66 |
// I'm using the first bin to record the number of input events.
|
67 |
pCutsPassed_->GetXaxis()->SetBinLabel( a+2, cutName.c_str() );
|
68 |
pCutFlow_->GetXaxis()->SetBinLabel( a+2, cutName.c_str() );
|
69 |
|
70 |
nameStream.str("");
|
71 |
nameStream << "N-1_" << cutName;
|
72 |
TH1F* pNewPlot=new TH1F( nameStream.str().c_str(), nameStream.str().c_str(), cutVariable.suggestedNumberOfBins(), cutVariable.suggestedLowerEdge(), cutVariable.suggestedUpperEdge() );
|
73 |
pNewPlot->SetDirectory(pNMinus1Directory);
|
74 |
nMinus1Plots_.push_back( pNewPlot );
|
75 |
|
76 |
// Book the histograms for all candidates
|
77 |
pNewPlot=new TH1F( cutName.c_str(), cutName.c_str(), cutVariable.suggestedNumberOfBins(), cutVariable.suggestedLowerEdge(), cutVariable.suggestedUpperEdge() );
|
78 |
pNewPlot->SetDirectory(pAllCandidatesDirectory);
|
79 |
allCandidatesPlots_.push_back( pNewPlot );
|
80 |
|
81 |
// Book the histograms for candidates that pass all cuts
|
82 |
pNewPlot=new TH1F( cutName.c_str(), cutName.c_str(), cutVariable.suggestedNumberOfBins(), cutVariable.suggestedLowerEdge(), cutVariable.suggestedUpperEdge() );
|
83 |
pNewPlot->SetDirectory(pPassedCandidatesDirectory);
|
84 |
passedCandidatesPlots_.push_back( pNewPlot );
|
85 |
}
|
86 |
|
87 |
//
|
88 |
// Now see if the cut set has defined any additional variables, i.e. variables that would
|
89 |
// interesting to look at but shouldn't be cut on.
|
90 |
//
|
91 |
size_t numberOfAdditionalVariables=pCutSet_->numberOfAdditionalVariables();
|
92 |
if( numberOfAdditionalVariables>0 )
|
93 |
{
|
94 |
if( createNTupleOfAdditionalVariables_ )
|
95 |
{
|
96 |
pAdditionalVariableTree_=new TTree("additionalVariables","Additional variables that haven't been cut on");
|
97 |
pAdditionalVariableTree_->SetDirectory( pDirectory );
|
98 |
}
|
99 |
|
100 |
for( size_t a=0; a<numberOfAdditionalVariables; ++a )
|
101 |
{
|
102 |
const trkupgradeanalysis::IHistogramVariable& variable=pCutSet_->additionalVariableAt(a);
|
103 |
TH1F* pNewPlot=new TH1F( variable.variableName().c_str(), variable.variableName().c_str(), variable.suggestedNumberOfBins(), variable.suggestedLowerEdge(), variable.suggestedUpperEdge() );
|
104 |
pNewPlot->SetDirectory(pDirectory);
|
105 |
additionalVariablePlots_.push_back(pNewPlot);
|
106 |
|
107 |
// Set the tree branch to point to the correct point in the values vector. The values
|
108 |
// vector will not change size so this *should* be safe.
|
109 |
if( pAdditionalVariableTree_ )
|
110 |
{
|
111 |
// Note that the branch address is initially set to NULL because the address is set before each fill.
|
112 |
// This is because if this class is copied the member addresses change, so I can't set the branch
|
113 |
// address to any members.
|
114 |
TBranch* pNewBranch=pAdditionalVariableTree_->Branch( variable.variableName().c_str(), NULL, (variable.variableName()+"/D").c_str() );
|
115 |
additionalVariableBranches_.push_back( pNewBranch ); // record the branch so that I can set the address individually
|
116 |
}
|
117 |
}
|
118 |
}
|
119 |
|
120 |
histogramHaveBeenBooked_=true;
|
121 |
}
|
122 |
|
123 |
void trkupgradeanalysis::CutSetPlotSet::fill( const VHbbCandidate& vhbbCandidate )
|
124 |
{
|
125 |
if( !histogramHaveBeenBooked_ ) throw std::runtime_error( "trkupgradeanalysis::CutSetPlotSet::book() - histograms have not been booked" );
|
126 |
|
127 |
bool candidatePassesAllCuts=false;
|
128 |
if( pCutSet_->applyCuts(vhbbCandidate) )
|
129 |
{
|
130 |
passedCandidateHistograms_.fill( vhbbCandidate );
|
131 |
candidatePassesAllCuts=true;
|
132 |
|
133 |
//
|
134 |
// Now fill the plots and tree for the additional variables if there are any.
|
135 |
//
|
136 |
|
137 |
// Need to keep track of the variables for the TTree to fill with (if there is one)
|
138 |
std::vector<double> additionalVariableValues( pCutSet_->numberOfAdditionalVariables() );
|
139 |
// Fill the histograms for the additional variables, and the ntuple if it has been requested
|
140 |
for( size_t a=0; a<pCutSet_->numberOfAdditionalVariables(); ++a )
|
141 |
{
|
142 |
// All these vectors should be set the same size, so I won't check again
|
143 |
Double_t value=pCutSet_->additionalVariableAt(a).histogrammableValue();
|
144 |
additionalVariableValues[a]=value; // store this, so that the TTree can access it
|
145 |
additionalVariablePlots_[a]->Fill(value);
|
146 |
|
147 |
// An ntuple might not have been requested, in which case don't try setting empty vectors
|
148 |
if( pAdditionalVariableTree_ ) additionalVariableBranches_[a]->SetAddress( &additionalVariableValues[a] );
|
149 |
}
|
150 |
if( pAdditionalVariableTree_ ) pAdditionalVariableTree_->Fill();
|
151 |
}
|
152 |
|
153 |
// Always fill the first bin so that I know how many candidates have been tested
|
154 |
pCutFlow_->Fill(0);
|
155 |
pCutsPassed_->Fill(0);
|
156 |
|
157 |
// Now see which individual cuts have been passed and fill the histogram
|
158 |
bool keepFillingCutFlowHistogram=true;
|
159 |
for( size_t a=0; a<pCutSet_->numberOfCuts(); ++a )
|
160 |
{
|
161 |
if( pCutSet_->cutNPassed(a) ) pCutsPassed_->Fill(a+1); // "a+1" because the first bin is how many candidates there are at the start
|
162 |
else keepFillingCutFlowHistogram=false;
|
163 |
|
164 |
if( keepFillingCutFlowHistogram ) pCutFlow_->Fill(a+1);
|
165 |
|
166 |
// Only fill the N-1 plots if all other cuts were passed
|
167 |
if( pCutSet_->everythingOtherThanCutNPassed(a) ) nMinus1Plots_[a]->Fill( pCutSet_->cutAt(a).cutVariable().histogrammableValue() );
|
168 |
// Always fill these plots for all of the candidates
|
169 |
allCandidatesPlots_[a]->Fill( pCutSet_->cutAt(a).cutVariable().histogrammableValue() );
|
170 |
// Only fill the passed candidates plots if all cuts were passed
|
171 |
if( candidatePassesAllCuts ) passedCandidatesPlots_[a]->Fill( pCutSet_->cutAt(a).cutVariable().histogrammableValue() );
|
172 |
}
|
173 |
|
174 |
}
|
175 |
|
176 |
void trkupgradeanalysis::CutSetPlotSet::fill( const trkupgradeanalysis::tools::NTupleRow& ntupleRow )
|
177 |
{
|
178 |
if( !histogramHaveBeenBooked_ ) throw std::runtime_error( "trkupgradeanalysis::CutSetPlotSet::book() - histograms have not been booked" );
|
179 |
|
180 |
bool candidatePassesAllCuts=false;
|
181 |
if( pCutSet_->applyCuts(ntupleRow) )
|
182 |
{
|
183 |
// TODO - implement this
|
184 |
// passedCandidateHistograms_.fill( ntupleRow );
|
185 |
candidatePassesAllCuts=true;
|
186 |
|
187 |
//
|
188 |
// Now fill the plots and tree for the additional variables if there are any.
|
189 |
//
|
190 |
|
191 |
// Need to keep track of the variables for the TTree to fill with (if there is one)
|
192 |
std::vector<double> additionalVariableValues( pCutSet_->numberOfAdditionalVariables() );
|
193 |
// Fill the histograms for the additional variables, and the ntuple if it has been requested
|
194 |
for( size_t a=0; a<pCutSet_->numberOfAdditionalVariables(); ++a )
|
195 |
{
|
196 |
// All these vectors should be set the same size, so I won't check again
|
197 |
Double_t value=pCutSet_->additionalVariableAt(a).histogrammableValue();
|
198 |
additionalVariableValues[a]=value; // store this, so that the TTree can access it
|
199 |
additionalVariablePlots_[a]->Fill(value);
|
200 |
|
201 |
// An ntuple might not have been requested, in which case don't try setting empty vectors
|
202 |
if( pAdditionalVariableTree_ ) additionalVariableBranches_[a]->SetAddress( &additionalVariableValues[a] );
|
203 |
}
|
204 |
if( pAdditionalVariableTree_ ) pAdditionalVariableTree_->Fill();
|
205 |
}
|
206 |
|
207 |
// Always fill the first bin so that I know how many candidates have been tested
|
208 |
pCutFlow_->Fill(0);
|
209 |
pCutsPassed_->Fill(0);
|
210 |
|
211 |
// Now see which individual cuts have been passed and fill the histogram
|
212 |
bool keepFillingCutFlowHistogram=true;
|
213 |
for( size_t a=0; a<pCutSet_->numberOfCuts(); ++a )
|
214 |
{
|
215 |
if( pCutSet_->cutNPassed(a) ) pCutsPassed_->Fill(a+1); // "a+1" because the first bin is how many candidates there are at the start
|
216 |
else keepFillingCutFlowHistogram=false;
|
217 |
|
218 |
if( keepFillingCutFlowHistogram ) pCutFlow_->Fill(a+1);
|
219 |
|
220 |
// Only fill the N-1 plots if all other cuts were passed
|
221 |
if( pCutSet_->everythingOtherThanCutNPassed(a) ) nMinus1Plots_[a]->Fill( pCutSet_->cutAt(a).cutVariable().histogrammableValue() );
|
222 |
// Always fill these plots for all of the candidates
|
223 |
allCandidatesPlots_[a]->Fill( pCutSet_->cutAt(a).cutVariable().histogrammableValue() );
|
224 |
// Only fill the passed candidates plots if all cuts were passed
|
225 |
if( candidatePassesAllCuts ) passedCandidatesPlots_[a]->Fill( pCutSet_->cutAt(a).cutVariable().histogrammableValue() );
|
226 |
}
|
227 |
|
228 |
}
|