|
DAS
3.0
Das Analysis System
|
|
void | getHLTJetResponse (const vector< fs::path > &inputs, const fs::path &output, const pt::ptree &config, const int steering, const DT::Slice slice={1, 0}) |
|
unique_ptr< TH3 > | makeRespHist (TString name, TString study) |
|
void | applyDataNormalisation (const vector< fs::path > &inputs, const fs::path &output, const pt::ptree &config, const int steering, const DT::Slice slice={1, 0}) |
|
void | reset (Weights &wgts, const double v=0) |
|
float | GetNormFactor (const vector< fs::path > &sumWgts, const float xsec) |
|
void | applyMClumi (const vector< fs::path > &inputs, const vector< fs::path > &sumWgts, const fs::path &output, const pt::ptree &config, const int steering, const DT::Slice slice={1, 0}) |
|
void | applyNormFactor (const vector< fs::path > &inputs, const fs::path &output, const pt::ptree &config, const int steering, const DT::Slice slice={1, 0}) |
|
void | getSumWeights (const vector< fs::path > &inputs, const fs::path &output, const pt::ptree &config, const int steering, const DT::Slice slice={1, 0}) |
|
std::vector< DAS::RecJet >::iterator | phaseSel (std::vector< DAS::RecJet > &recjets) |
|
std::ostream & | operator<< (std::ostream &Stream, const TriggerLumi &tr_lu) |
|
float | getPrescale (Trigger *trigger, size_t indx) |
|
void | getTriggerCurves (const vector< fs::path > &inputs, const fs::path &output, const pt::ptree &config, const int steering, const DT::Slice slice={1, 0}) |
|
void | getTriggerTurnons (const fs::path &input, const fs::path &outputRoot, const fs::path &outputTxt, const pt::ptree &config, const int steering) |
|
DAS::FourVector | match (const DAS::FourVector &jet, const std::vector< DAS::FourVector > *hltJets) |
|
float | GetX (TF1 *f) |
|
template<typename STREAM > |
TF1 * | FitTriggerEfficiency (int trigger, TH1 *h, STREAM &Stream, int from, const char *options="NQERS") |
|
template<typename STREAM > |
float | GetTriggerEfficiency (int trigger, TH1 *h, STREAM &Stream, float from, float minEff) |
|
◆ anonymous enum
Enumerator |
---|
WEIGHT | use the weights
|
SIGN | use the sign
|
CUTOFF | apply a selection on the weight
|
◆ applyDataNormalisation()
void DAS::Normalisation::applyDataNormalisation |
( |
const vector< fs::path > & |
inputs, |
|
|
const fs::path & |
output, |
|
|
const pt::ptree & |
config, |
|
|
const int |
steering, |
|
|
const DT::Slice |
slice = {1,0} |
|
) |
| |
Apply the the kinematic selection, ensuring that events in the dataset have fired a trigger and correcting the weight of the events with the associated trigger prescales, trigger efficiency, and total luminosity. The weight $\frac{ \text{Prescale} * \mathcal{L}^{-1} }{ \epsilon_\text{trigger} } $ is applied by event. The argument 'strategy' defines the selection criterion of the events and the calculation of the weight (see functor in applyDataNormalisation.h).
- Todo:
- add lumi unc variations
- Todo:
- revisit the logic (having inputs modified + a return object may be confusing)
- Todo:
- reimplement the logic to avoid a selection on the weight
- Parameters
-
inputs | input ROOT files (n-tuple) |
output | output ROOT file (n-tuple) |
config | config handled with `Darwin::Tools::Options` |
steering | parameters obtained from explicit options |
slice | number and index of slice |
51 cout << __func__ <<
' ' << slice <<
" start" << endl;
54 auto tIn = flow.GetInputTree(
inputs, slice);
55 auto [fOut, tOut] = flow.GetOutput(output);
59 auto isMC = metainfo.Get<
bool>(
"flags",
"isMC");
61 BOOST_THROW_EXCEPTION(
DE::BadInput(
"Only real data may be used as input.", metainfo) );
64 auto recEvt = flow.GetBranchReadWrite<RecEvent>(
"recEvent");
65 auto trigger = flow.GetBranchReadOnly<Trigger>(
"jetTrigger");
68 auto recJets = flow.GetBranchReadOnly<vector<RecJet>>(
"recJets");
69 auto hltJets = flow.GetBranchReadOnly<vector<FourVector>>(
"hltJets");
71 int year = metainfo.Get<
int>(
"flags",
"year");
74 auto lumi_file =
config.get<fs::path>(
"corrections.normalisation.luminosities" ),
75 unc_file =
config.get<fs::path>(
"corrections.normalisation.uncertainties"),
76 turnon_file =
config.get<fs::path>(
"corrections.normalisation.turnons" ),
77 efficiencies =
config.get<fs::path>(
"corrections.normalisation.efficiencies" );
78 auto strategy =
config.get<
string>(
"corrections.normalisation.strategy"),
79 method =
config.get<
string>(
"corrections.normalisation.method" );
80 Functor normalisation(lumi_file, turnon_file, efficiencies, strategy,
method,
year);
81 LumiUnc lumi_unc(unc_file,
year);
84 bool applySyst = steering &
DT::syst;
86 for (
string source: lumi_unc.sources)
87 metainfo.Set<
string>(
"variations", RecEvent::WeightVar,
source);
91 ControlPlots corrNoTrigEff(
"corrNoTrigEff");
93 vector<ControlPlots> corr { ControlPlots(
"nominal") };
94 TList * ev_wgts = metainfo.List(
"variations", RecEvent::WeightVar);
95 for (TObject * obj: *ev_wgts) {
96 auto name =
dynamic_cast<TObjString*
>(obj)->GetString();
97 corr.push_back(ControlPlots(
name));
102 for (
DT::Looper looper(tIn); looper(); ++looper) {
109 if (recJets->size() == 0)
continue;
111 RecJet leadingJet = normalisation(*recEvt, *recJets, *hltJets, *trigger);
112 cout <<
"leadingJet: " << leadingJet << endl;
117 if (recEvt->weights.front() <= 0)
continue;
118 if (steering &
DT::fill) tOut->Fill();
120 float evtWgts = recEvt->weights.front();
121 float efficiency = normalisation.eff(leadingJet);
123 cout <<
"evtWgts = " << evtWgts <<
'\n'
124 <<
"efficiency = " << efficiency << endl;
125 if (efficiency <= 0)
continue;
127 corrNoTrigEff(*recJets, evtWgts*efficiency);
128 for (
size_t i = 0; i < corr.size(); ++i)
129 corr.at(i)(*recJets, recEvt->weights.at(i));
134 for (
auto& jet: *recJets) {
135 float y = jet.AbsRap();
136 float w = recEvt->weights.front();
137 normalisation.eff.contribs.at(normalisation.ibit)->Fill(jet.CorrPt(), y,
w);
142 corrNoTrigEff.Write(fOut);
143 for (
size_t i = 0; i < corr.size(); ++i)
144 corr.at(i).Write(fOut);
145 TDirectory * controlplots = fOut->mkdir(
"controlplots");
147 for (TH2 * h: normalisation.eff.contribs) {
148 h->SetDirectory(controlplots);
152 metainfo.Set<
bool>(
"git",
"complete",
true);
154 cout << __func__ <<
' ' << slice <<
" stop" << endl;
◆ applyMClumi()
void DAS::Normalisation::applyMClumi |
( |
const vector< fs::path > & |
inputs, |
|
|
const vector< fs::path > & |
sumWgts, |
|
|
const fs::path & |
output, |
|
|
const pt::ptree & |
config, |
|
|
const int |
steering, |
|
|
const DT::Slice |
slice = {1,0} |
|
) |
| |
Normalise with sum of weights (to be computed) and cross section (given)
- Note
- A cut-off for events with hard scale above 5 TeV is applied, since these events are not realistic
- Todo:
- Events with scale > 5TeV are removed because Pythia used to generate too many of them. Check that this is still needed and that the cut is still appropriate.
- Parameters
-
inputs | input ROOT files (n-tuple) |
sumWgts | input ROOT files (histogram) |
output | output ROOT file (n-tuple) |
config | config handled with `Darwin::Tools::Options` |
steering | parameters obtained from explicit options |
slice | number and index of slice |
66 cout << __func__ <<
' ' << slice <<
" start" << endl;
69 auto tIn = flow.GetInputTree(
inputs, slice);
70 auto [fOut, tOut] = flow.GetOutput(output);
74 auto isMC = metainfo.Get<
bool>(
"flags",
"isMC");
75 if (!
isMC) BOOST_THROW_EXCEPTION(
DE::BadInput(
"Only MC may be used as input.",
76 make_unique<TFile>(
inputs.front().c_str() )) );
79 auto xsection =
config.get<
float>(
"corrections.MCnormalisation.xsection");
81 metainfo.Set<
float>(
"corrections",
"MCnormalisation",
"xsection", xsection);
84 auto genEvt = flow.GetBranchReadWrite<GenEvent>(
"genEvent");
85 auto recEvt = flow.GetBranchReadOnly<RecEvent>(
"recEvent");
86 auto genJets = flow.GetBranchReadOnly<vector<GenJet>>(
"genJets",
DT::facultative);
87 auto recJets = flow.GetBranchReadOnly<vector<RecJet>>(
"recJets",
DT::facultative);
91 ControlPlots plots(
"controlplots");
93 for (
DT::Looper looper(tIn); looper(); ++looper) {
99 if (genEvt->hard_scale > 5000 )
continue;
102 if (genEvt->weights.size() != 1 || recEvt->weights.size() != 1)
104 if (recJets !=
nullptr && recJets->size() > 0 && recJets->front().scales.size() > 1)
105 BOOST_THROW_EXCEPTION(
DE::AnomalousEvent(
"Unexpected jet energy scale variations", tIn) );
108 genEvt->weights.front() *= factor;
109 if (steering &
DT::fill) tOut->Fill();
112 if (genJets !=
nullptr)
113 plots(*genJets, genEvt->weights.front() );
114 if (recJets !=
nullptr)
115 plots(*recJets, genEvt->weights.front() * recEvt->weights.front());
118 metainfo.Set<
bool>(
"git",
"complete",
true);
122 cout << __func__ <<
' ' << slice <<
" stop" << endl;
◆ applyNormFactor()
void DAS::Normalisation::applyNormFactor |
( |
const vector< fs::path > & |
inputs, |
|
|
const fs::path & |
output, |
|
|
const pt::ptree & |
config, |
|
|
const int |
steering, |
|
|
const DT::Slice |
slice = {1,0} |
|
) |
| |
Multiplies the gen weight of every event by a factor provided on the command line.
- Parameters
-
inputs | input ROOT files (n-tuple) |
output | output ROOT file (n-tuple) |
config | config handled with `Darwin::Tools::Options` |
steering | parameters obtained from explicit options |
slice | number and index of slice |
44 cout << __func__ <<
' ' << slice <<
" start" << endl;
47 auto tIn = flow.GetInputTree(
inputs, slice);
48 auto tOut = flow.GetOutputTree(output);
52 auto isMC = metainfo.Get<
bool>(
"flags",
"isMC");
53 if (!
isMC) BOOST_THROW_EXCEPTION(
DE::BadInput(
"Only MC may be used as input.",
54 make_unique<TFile>(
inputs.front().c_str() )) );
56 const float factor =
config.get<
float>(
"corrections.normFactor");
57 metainfo.Set<
float>(
"corrections",
"normFactor", factor);
60 auto evnt = flow.GetBranchReadOnly<GenEvent>(
"genEvent");
62 for (
DT::Looper looper(tIn); looper(); ++looper) {
67 if (evnt->weights.size() != 1)
71 for (
auto&
weight: evnt->weights)
74 if (steering &
DT::fill) tOut->Fill();
77 metainfo.Set<
bool>(
"git",
"complete",
true);
79 cout << __func__ <<
' ' << slice <<
" stop" << endl;
◆ FitTriggerEfficiency()
TF1* DAS::Normalisation::FitTriggerEfficiency |
( |
int |
trigger, |
|
|
TH1 * |
h, |
|
|
STREAM & |
Stream, |
|
|
int |
from, |
|
|
const char * |
options = "NQERS" |
|
) |
| |
Fit the trigger efficiency with sigmoid function in [trigger, 3* trigger], where trigger is the HLT pt threshold.
The sigmoid function is defined as follows:
\epsilon (p_T) = a + 0.5 \times (1-a) \times \left( 1 + \erf \left( \frac{p_T - \mu}{\sigma} \right) \right)
where a, $\mu$ and $\sigma$ are the three parameters.
NOTE:
- the output is very sensitive to the fit range
- unclear if/how JES uncertainties should be taken into account
- Parameters
-
trigger | trigger HLT threshold |
h | efficiency histogram |
Stream | `cout` or file |
from | last turnon, to know from where the ref is efficient |
options | fit options for TF1 function |
56 int mbin = h->GetXaxis()->FindBin( from),
57 Mbin = h->GetXaxis()->FindBin(3*from);
58 float m = h->GetBinLowEdge(mbin+1), M = h->GetBinLowEdge(Mbin);
59 for (
int bin = 0; bin <= mbin; ++bin) {
60 h->SetBinContent(bin, 0);
61 h->SetBinError (bin, 0);
63 for (
int bin = Mbin+1; bin <= h->GetNbinsX()+1; ++bin) {
64 h->SetBinContent(bin, 0);
65 h->SetBinError (bin, 0);
68 cout <<
"Fitting trigger " << trigger <<
" from " << m <<
" to " << M << endl;
71 TF1 *
f =
new TF1(Form(
"sigmoid%d", trigger),
72 "[0]+0.5*(1-[0])*(1+erf((x-[1])/[2]))",
75 f->SetParNames(
"a",
"#mu",
"#sigma");
78 f->SetParameter(0,0.1);
79 f->SetParLimits(0,0,0.9);
81 f->SetParameter(1,1.1*trigger);
82 f->SetParLimits(1,m,M);
84 f->SetParameter(2,10);
85 f->SetParLimits(2,1,150);
90 float turnon =
GetX(
f);
92 Stream << trigger <<
'\t' << turnon <<
'\n';
◆ getHLTJetResponse()
void DAS::Normalisation::getHLTJetResponse |
( |
const vector< fs::path > & |
inputs, |
|
|
const fs::path & |
output, |
|
|
const pt::ptree & |
config, |
|
|
const int |
steering, |
|
|
const DT::Slice |
slice = {1,0} |
|
) |
| |
Get HLT single-jet response in bins of kinematics in real data. The output can be used as input to fitJetResponse to determine and understand the deviations from the Gaussian expectations, which prevent from fitting the trigger efficiency with the error function.
- Parameters
-
inputs | input ROOT files (n-tuples) |
output | name of output ROOT file (histograms) |
config | config file from `DTOptions` |
steering | steering parameters from `DTOptions` |
slice | slices for running |
49 cout << __func__ <<
' ' << slice <<
" start" << endl;
52 auto tIn = flow.GetInputTree(
inputs, slice);
53 auto [fOut, tOut] = flow.GetOutput(output);
57 auto isMC = metainfo.Get<
bool>(
"flags",
"isMC");
59 BOOST_THROW_EXCEPTION(
DE::BadInput(
"Only DATA may be used as input.", metainfo) );
61 auto rEv = flow.GetBranchReadOnly<RecEvent>(
"recEvent");
62 auto recjets = flow.GetBranchReadOnly<vector<RecJet>>(
"recJets");
63 auto hltjets = flow.GetBranchReadOnly<vector<FourVector>>(
"hltJets");
65 unique_ptr<TH3> inclResp =
makeRespHist(
"inclusive",
"HLT");
67 for (
DT::Looper looper(tIn); looper(); ++looper) {
71 auto recWgt = rEv->weights.front();
76 auto pthlt = hltjet.Pt();
78 int pthltbin = inclResp->GetXaxis()->FindBin(pthlt);
79 double hlt_lowedge = inclResp->GetXaxis()->GetBinLowEdge(pthltbin);
85 inclResp->Fill(pthlt, yrec,
response, recWgt);
91 inclResp->SetDirectory(fOut);
92 inclResp->SetTitle(
"Response");
93 inclResp->Write(
"Response");
95 metainfo.Set<
bool>(
"git",
"complete",
true);
97 cout << __func__ <<
' ' << slice <<
" end" << endl;
◆ GetNormFactor()
float DAS::Normalisation::GetNormFactor |
( |
const vector< fs::path > & |
sumWgts, |
|
|
const float |
xsec |
|
) |
| |
Retrieve the sum of the weights obtained with getSumWeights
and combines it with the input cross section to calculate the normalisation factor.
- Parameters
-
sumWgts | file containing the hist |
xsec | cross section value |
40 auto h = DT::GetHist<TH2>(sumWgts,
"hSumWgt");
41 auto sumw = h->Integral(0, -1,
44 BOOST_THROW_EXCEPTION(
DE::BadInput(
"Negative sum of weights.", h) );
46 BOOST_THROW_EXCEPTION( invalid_argument(
"Negative cross section.") );
47 auto factor = xsec/sumw;
48 cout << xsec <<
'/' << sumw <<
'=' << factor << endl;
◆ getPrescale()
float DAS::Normalisation::getPrescale |
( |
Trigger * |
trigger, |
|
|
size_t |
indx |
|
) |
| |
96 float preHLT = trigger->PreHLT[indx];
97 float preL1min = trigger->PreL1min[indx];
98 float preL1max = trigger->PreL1max[indx];
99 assert(preL1min == preL1max);
100 float prescale = preHLT * preL1min;
◆ getSumWeights()
void DAS::Normalisation::getSumWeights |
( |
const vector< fs::path > & |
inputs, |
|
|
const fs::path & |
output, |
|
|
const pt::ptree & |
config, |
|
|
const int |
steering, |
|
|
const DT::Slice |
slice = {1,0} |
|
) |
| |
Sum the weights from ROOT n-tuple. Mostly useful for MC to estimate the effective number of events, which is necessary to normalise.
The histogram is filled in a way so that it can be used for two purposes:
- provide a distribution of the weights and choose a max weight,
- extract the normalisation factor by takaing its integral.
- Note
- The values beyond
maxAbsValue
are filled a 2nd time in the overflow with the opposite weight. The truncated sum of the weights is then obtained from the integral by including the overflow.
- Parameters
-
inputs | input ROOT files (n-tuple) |
output | output ROOT file (histograms) |
config | config handled with `Darwin::Tools::Options` |
steering | parameters obtained from explicit options |
slice | number and index of slice |
48 cout << __func__ <<
' ' << slice <<
" start" << endl;
51 auto tIn = flow.GetInputTree(
inputs, slice);
52 auto tOut = flow.GetOutputTree(output);
56 auto isMC = metainfo.Get<
bool>(
"flags",
"isMC");
57 if (!
isMC) BOOST_THROW_EXCEPTION(
DE::BadInput(
"Only MC may be used as input.",
58 make_unique<TFile>(
inputs.front().c_str() )) );
60 const auto maxAbsValue =
config.get<
float>(
"corrections.weights.maxAbsValue");
61 const auto mode =
config.get<
string>(
"corrections.weights.mode");
63 cout <<
"maxAbsValue = " << maxAbsValue << endl;
65 auto evnt = flow.GetBranchReadOnly<GenEvent>(
"genEvent");
67 TString title =
";log_{10}(w);sign;#sum_{i=1}^{events} w_{i}";
68 if (maxAbsValue > 0) title = Form(
"w < %d", maxAbsValue);
69 auto h = make_unique<TH2D>(
"hSumWgt", title, 100, 3, 40,
71 const double overflow = h->GetXaxis()->GetXmax()+1.;
75 else if (mode ==
"signOnly") wm =
SIGN;
76 else if (mode !=
"count" )
77 BOOST_THROW_EXCEPTION( invalid_argument(mode +
" is unknown") );
79 if (maxAbsValue > 0) wm |=
CUTOFF;
81 cout <<
"wm = " << bitset<8>(wm) << endl;
84 cout << setw(20) <<
"w"
86 << setw(20) <<
"x [log10(abs(w))]"
87 << setw(20) <<
"y [sign]"
88 << setw(20) <<
"z [eff. weight]" << endl;
90 for (
DT::Looper looper(tIn); looper(); ++looper) {
94 const double w = evnt->weights.front();
95 if (
w == 0.)
continue;
98 BOOST_THROW_EXCEPTION( runtime_error(
"Infinite or NaN weight:"s +
w) );
104 const double absw = std::abs(
w),
107 double z = wm &
WEIGHT ? absw : 1;
108 if (wm &
SIGN) z = copysign(z,
w);
110 cout << setw(20) <<
w
114 << setw(20) << z << endl;
119 cerr <<
orange <<
"Warning: a good weight is being filled in the overflow.\n" <<
def;
124 if ((wm &
CUTOFF) && absw >= maxAbsValue)
125 h->Fill(overflow, y, -z);
128 metainfo.Set<
bool>(
"git",
"complete",
true);
132 cout << __func__ <<
' ' << slice <<
" end" << endl;
◆ getTriggerCurves()
void DAS::Normalisation::getTriggerCurves |
( |
const vector< fs::path > & |
inputs, |
|
|
const fs::path & |
output, |
|
|
const pt::ptree & |
config, |
|
|
const int |
steering, |
|
|
const DT::Slice |
slice = {1,0} |
|
) |
| |
Get trigger curves from the data n-tuples.
- Todo:
- fix error
- Todo:
- fix error
- Parameters
-
inputs | input ROOT file (n-tuple) |
output | output ROOT file (n-tuple) |
config | config handled with `Darwin::Tools::options` |
steering | parameters obtained from explicit options |
slice | number and index of slice |
118 auto tIn = flow.GetInputTree(
inputs, slice);
119 auto [fOut, tOut] = flow.GetOutput(output);
124 const auto usePrescales =
config.get<
bool>(
"corrections.normalisation.use_prescales");
125 metainfo.Set<
bool>(
"corrections",
"normalisation",
"use_prescales", usePrescales);
127 auto lumi_file =
config.get<fs::path>(
"corrections.normalisation.luminosities");
128 pt::ptree triggers_lumi;
129 pt::read_info(lumi_file.string(), triggers_lumi);
130 for (
auto const& trigger_lumi: triggers_lumi)
131 thresholds.push_back(stoi(trigger_lumi.first));
133 metainfo.Set<fs::path>(
"corrections",
"normalisation",
"luminosities", lumi_file);
135 auto trigger = flow.GetBranchReadOnly<Trigger>(
"jetTrigger");
136 auto recjets = flow.GetBranchReadOnly<vector<RecJet>>(
"recJets");
137 auto hltjets = flow.GetBranchReadOnly<vector<FourVector>>(
"hltJets");
139 map<TString, size_t> methods {
141 {
"emulationShift", 2},
146 TH1 * Deta =
new TH1F(
"deta",
"; #Delta #eta; nevt", 200, -5, 5);
147 TH1 * Dphi =
new TH1F(
"dphi",
"; #Delta #phi; nevt", 200, -M_PI, M_PI);
148 TH1 * dR =
new TH1F(
"dR" ,
"; #Delta R; nevt" , 200, 0, 10);
150 map<TString, map<int, Efficiency>> curves;
151 for (
auto method: methods)
154 cout <<
method.first <<
'\t' << t <<
'\n';
155 curves[
method.first].insert( {t, Efficiency(
method.first, t)} );
159 for (
DT::Looper looper(tIn); looper(); ++looper) {
164 size_t nbits = trigger->Bit.size();
166 BOOST_THROW_EXCEPTION(
DE::AnomalousEvent( Form(
"nbits = %ld < thresholds.size() = %ld",
170 if (
recjets->size() == 0)
continue;
172 for (
const RecJet& pfjet: *
recjets){
176 Deta->Fill(pfjet.p4.Eta() - hltjet.Eta(), pfjet.weights.front());
177 Dphi->Fill(DeltaPhi(pfjet.p4,hltjet), pfjet.weights.front());
178 dR->Fill(DeltaR(pfjet.p4, hltjet), pfjet.weights.front());
179 pt_correlation->Fill(pfjet.CorrPt(), hltjet.Pt(), pfjet.weights.front());
186 if (leadingInTk ==
recjets->end())
continue;
189 pfjet0 *= leadingInTk->scales.front();
195 for (
auto method: methods) {
197 if (
method.first.Contains(
"TnP"))
continue;
198 size_t shift =
method.second;
200 for (
size_t i = shift; i <
thresholds.size(); ++i) {
203 auto& eff = curves.at(
method.first).at(t);
205 eff.hAll->Fill(pfjet0.Pt(), hltjet0.Pt());
208 if (!trigger->Bit[i-shift])
continue;
209 eff.hFired->Fill(pfjet0.Pt(), hltjet0.Pt());
211 if (hltjet0.Pt() <
thresholds.at(i-shift))
continue;
212 eff.hFiredThreshold->Fill(pfjet0.Pt(), hltjet0.Pt());
214 float wgt = usePrescales ?
getPrescale(trigger, i-shift) : 1;
215 bool fired = hltjet0.Pt() > t;
216 eff.Fill(pfjet0, fired, wgt*
recjets->front().weights.front());
218 eff.hHLTmap->Fill( pfjet0.Phi(),pfjet0.Eta(),wgt*
recjets->front().weights.front() );
223 for (
size_t i = 0; i <
thresholds.size(); ++i) {
226 auto& eff = curves.at(
"TnP").at(t);
228 eff.hAll->Fill(pfjet0.Pt(), hltjet0.Pt());
231 if (!trigger->Bit[i])
233 eff.hFired->Fill(pfjet0.Pt(), hltjet0.Pt());
240 if (DeltaPhi(
recjets->at(0).p4,
recjets->at(1).p4) < 2.4)
continue;
243 const double pt0 =
recjets->at(0).CorrPt(),
246 if (pt2 > 0.15*(pt0 + pt1))
251 static TRandom3 Rand( metainfo.Seed<10989678>(slice));
252 double r = Rand.Uniform();
257 pfprobe =
recjets->at(iprobe).p4;
259 float pfprobe_wgt =
recjets->at(iprobe).weights.front();
260 float pftag_wgt =
recjets->at(itag).weights.front();
262 pftag *=
recjets->at(itag ).scales.front();
263 pfprobe *=
recjets->at(iprobe).scales.front();
266 if (std::abs(
recjets->at(itag).p4.Eta()) > 1.3)
continue;
277 if (hlttag.Pt() > t) {
278 eff.hFiredThreshold->Fill(pfjet0.Pt(), hltjet0.Pt());
281 bool fired = hltprobe.Pt() > t;
283 float wgt = usePrescales ?
getPrescale(trigger, i) : 1;
284 eff.Fill(pfprobe, fired, wgt * pftag_wgt * pfprobe_wgt);
285 eff.hHLTmap->Fill( pfjet0.Phi(),pfjet0.Eta(),wgt*
recjets->front().weights.front() );
290 cout <<
"Writing to file" << endl;
291 for (
auto&
method: curves) {
293 auto d = fOut->mkdir(
method.first);
294 for (
auto& curve:
method.second)
295 curve.second.Write(d);
301 pt_correlation->Write();
303 metainfo.Set<
bool>(
"git",
"complete",
true);
◆ GetTriggerEfficiency()
float DAS::Normalisation::GetTriggerEfficiency |
( |
int |
trigger, |
|
|
TH1 * |
h, |
|
|
STREAM & |
Stream, |
|
|
float |
from, |
|
|
float |
minEff |
|
) |
| |
DON'T fit the trigger efficiency but just find the first bin above threshold
- Todo:
- Where does the factor 6 come from?
- Parameters
-
trigger | trigger HLT threshold |
h | efficiency histogram |
Stream | `cout` or file |
from | last turnon, to know from where the ref is efficient |
minEff | min efficiency (e.g. different for barrel and forward region) |
107 int mbin = h->GetXaxis()->FindBin( from),
108 Mbin = h->GetXaxis()->FindBin(6*from);
109 for (
int bin = 0; bin < mbin; ++bin) {
110 h->SetBinContent(bin, 0);
111 h->SetBinError (bin, 0);
113 for (
int bin = Mbin+1; bin <= h->GetNbinsX()+1; ++bin) {
114 h->SetBinContent(bin, 0);
115 h->SetBinError (bin, 0);
117 for (
int bin = mbin; bin <= Mbin; ++bin) {
118 float content = h->GetBinContent(bin);
119 if (content < minEff)
continue;
120 float turnon = h->GetBinLowEdge(bin);
121 Stream << trigger <<
'\t' << turnon <<
'\n';
◆ getTriggerTurnons()
void DAS::Normalisation::getTriggerTurnons |
( |
const fs::path & |
input, |
|
|
const fs::path & |
outputRoot, |
|
|
const fs::path & |
outputTxt, |
|
|
const pt::ptree & |
config, |
|
|
const int |
steering |
|
) |
| |
Get the trigger turn-on points from the trigger curves.
- Todo:
- Use metainfo
- Todo:
- Get year from metainfo?
- Todo:
- Get lumis from metainfo?
- Todo:
- implement a more general logic to use only rapidity <3 turnons to determine the overall turnon
- Parameters
-
input | input ROOT file (n-tuple) |
outputRoot | output ROOT file with efficiency |
outputTxt | output text file with turn-ons |
config | config handled with `Darwin::Tools::options` |
steering | parameters obtained from explicit options |
46 cout << __func__ <<
" start" << endl;
55 cout << setw(10) <<
"trigger";
56 for (
auto yBin:
yBins) cout << setw(18) << yBin;
59 pt::ptree triggers_lumi;
60 auto lumi_file =
config.get<fs::path>(
"corrections.normalisation.luminosities");
61 pt::read_info(lumi_file.c_str(), triggers_lumi);
62 vector<int> triggerThresholds;
63 for (
auto trigger_lumi: triggers_lumi)
64 triggerThresholds.push_back(stoi(trigger_lumi.first));
66 auto fIn = make_unique<TFile>(
input.c_str(),
"READ");
67 map<int, int> turnonsFinal;
68 TIter Next(fIn->GetListOfKeys()) ;
70 TString defMethod =
"TnP";
71 while ( (
key =
dynamic_cast<TKey*
>(Next())) ) {
72 if (TString(
key->ReadObj()->ClassName()) != TString(
"TDirectoryFile"))
76 auto dIn =
dynamic_cast<TDirectory*
>(
key->ReadObj());
78 int lastturnon = triggerThresholds.front();
81 TString
method = dIn->GetName();
85 auto dOut = fOut->mkdir(
method);
87 TIter Next2(dIn->GetListOfKeys()) ;
88 while ( (
key =
dynamic_cast<TKey*
>(Next2())) ) {
89 if (TString(
key->ReadObj()->ClassName()) != TString(
"TDirectoryFile"))
93 auto ddIn =
dynamic_cast<TDirectory*
>(
key->ReadObj());
95 TString trigName = ddIn->GetName();
96 assert(trigName.Contains(
"HLT"));
99 auto ddOut = dOut->mkdir(trigName);
101 trigName.ReplaceAll(
"HLT",
"");
102 int trigger = trigName.Atoi();
103 if (
method ==
"TnP" && trigger < triggerThresholds.at(0))
continue;
104 if (
method ==
"emulation" && trigger < triggerThresholds.at(1))
continue;
105 if (
method ==
"emulationShift" && trigger < triggerThresholds.at(2))
continue;
106 cout << setw(10) << trigger;
108 auto h2 = unique_ptr<TH2>(ddIn->Get<TH2>(
"test"));
110 auto den = unique_ptr<TH2>(ddIn->Get<TH2>(
"ref"));
111 h2->Divide(h2.get(), den.get(), 1, 1,
"B");
116 h2->SetDirectory(ddOut);
117 h2->SetName(
"efficiency");
119 vector<int> turnonsNow;
120 for (
int y = 1; y <= h2->GetNbinsY(); ++y) {
123 auto h1 = unique_ptr<TH1>(h2->ProjectionX(Form(
"efficiency_ybin%d", y), y, y));
125 static ostream bitBucket(0);
139 float from = h1->GetBinLowEdge(h1->FindBin(lastturnon)+1);
141 h1->SetTitle(Form(
"%d (%.3f)", turnon,
threshold));
142 h1->SetDirectory(dOut);
144 turnonsNow.push_back(turnon);
149 auto maxturnon = max_element(turnonsNow.begin(), turnonsNow.begin()+6);
150 h2->SetTitle(Form(
"%d", *maxturnon));
152 for (
auto turnon: turnonsNow) {
153 if (turnon == *maxturnon) cout <<
"\x1B[32m\e[1m";
154 if (turnon < 0) cout <<
"\x1B[31m\e[1m";
155 cout << setw(18) << turnon;
156 cout <<
"\x1B[30m\e[0m";
162 turnonsFinal[trigger] = *maxturnon;
164 defMethod =
"emulation";
165 lastturnon = *maxturnon;
167 if (lastturnon == -1) {
168 cerr <<
"Didn't find any turnon for trigger " << trigger <<
'\n';
169 lastturnon = trigger;
174 pt::ptree turnon_file;
175 for (
auto& turnon: turnonsFinal)
176 turnon_file.put<
int>(to_string(turnon.first), turnon.second);
177 pt::write_info(outputTxt.string(), turnon_file);
179 cout << __func__ <<
" end" << endl;
◆ GetX()
float DAS::Normalisation::GetX |
( |
TF1 * |
f | ) |
|
Replaces TF1::GetX() which does not return the same value when run after compilation or in interactive mode...
Principle: just scan the pt axis with step = 1 until eff > 0.995
22 double m = 0, M = 7000;
25 for (
float pt = m;
pt < M; ++
pt)
29 cerr <<
"No threshold was found from " << m <<
" to " << M <<
".\nAborting.\n";
◆ makeRespHist()
unique_ptr<TH3> DAS::Normalisation::makeRespHist |
( |
TString |
name, |
|
|
TString |
study |
|
) |
| |
Create TH3 histograms for the Jet response and HLT response.
- Parameters
-
name | abitrary name |
study | expecting JER or HLT |
25 static int nResBins = 200;
26 static auto resBins =
getBinning(nResBins, 0, 2);
30 static const char * axistitles =
";p_{T}^{HLT};|#eta^{rec}|;#frac{p_{T}^{rec}}{p_{T}^{HLT bin low edge}}";
31 static const vector<double> HLT_binning = {40., 60., 80., 140., 200., 260., 320., 400., 450., 500.};
32 static int nHLTbins = HLT_binning.size()-1;
33 h = make_unique<TH3D>(
name, axistitles,
34 nHLTbins, HLT_binning.data(),
36 nResBins, resBins.data());
38 else if (study ==
"JER"){
41 static const char * axistitles =
";p_{T}^{gen};|#eta^{rec}|;#frac{p_{T}^{rec}}{p_{T}^{gen}}";
42 h = make_unique<TH3D>(
name, axistitles,
45 nResBins, resBins.data());
48 h->SetDirectory(
nullptr);
◆ match()
8 for (
const auto& hltjet: *hltJets){
9 using ROOT::Math::VectorUtil::DeltaR;
10 if (DeltaR(hltjet, jet) < 0.3)
◆ operator<<()
std::ostream& DAS::Normalisation::operator<< |
( |
std::ostream & |
Stream, |
|
|
const TriggerLumi & |
tr_lu |
|
) |
| |
25 Stream << tr_lu.pt <<
'\t' << tr_lu.turnon <<
'\t' << tr_lu.weight <<
'\t' << 1./tr_lu.weight;
◆ phaseSel()
10 auto leadingInTk =
recjets.begin();
11 while (leadingInTk !=
recjets.end()
12 && std::abs(leadingInTk->Rapidity()) >= 3.0)
◆ reset()
void DAS::Normalisation::reset |
( |
Weights & |
wgts, |
|
|
const double |
v = 0 |
|
) |
| |
|
inline |
28 {
std::fill(wgts.begin(), wgts.end(), Weight{v,0}); }
◆ nThresholds
◆ threshold
const float threshold = 0.995 |
◆ thresholds
vector<double> thresholds |
name
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:48
std::vector< DAS::RecJet >::iterator phaseSel(std::vector< DAS::RecJet > &recjets)
Definition: PhaseSelection.h:9
method
Definition: Core-gitclone-lastrun.txt:5
float GetNormFactor(const vector< fs::path > &sumWgts, const float xsec)
Definition: applyMClumi.cc:37
cerr
Definition: Ntupliser_cfg.py:93
static const std::vector< double > y_edges
Definition: binnings.h:36
options
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:41
pt
Definition: jmarExample.py:19
static bool verbose
Definition: Step.h:40
vector< double > thresholds
Definition: getTriggerCurves.cc:41
static const char * def
Definition: Step.h:36
FourVector p4
raw four-momentum directly after reconstruction
Definition: PhysicsObject.h:50
int nThresholds
Definition: getTriggerCurves.cc:42
int year
Definition: Ntupliser_cfg.py:63
source
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:39
static const std::vector< double > pt_JERC_edges
Definition: common.h:17
static const std::vector< double > pt_edges
Definition: binnings.h:33
f
Definition: Ntupliser_cfg.py:256
string key
Definition: jercExample.py:109
std::vector< double > getBinning(int nBins, float first, float last)
Definition: common.h:53
static const float w
Definition: common.h:51
@ SIGN
use the sign
Definition: getSumWeights.cc:29
unique_ptr< TH3 > makeRespHist(TString name, TString study)
Create TH3 histograms for the Jet response and HLT response.
Definition: MakeResponseHistos.h:20
float AbsRap(const Uncertainties::Variation &=Uncertainties::nominal) const final
absolute rapidity
Definition: PhysicsObject.h:58
DAS::RecJet recjet
Definition: classes.h:15
DAS::Weight weight
Definition: classes.h:11
@ WEIGHT
use the weights
Definition: getSumWeights.cc:28
config
Definition: Ntupliser_cfg.py:264
static const char * orange
Definition: colours.h:6
input
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:35
recjets
Definition: Ntupliser_cfg.py:273
static const std::vector< double > abseta_edges
JERC binning (taken from JERCProtoLab repo, /macros/common_info/common_binning.hpp)
Definition: common.h:22
float CorrPt(size_t i=0) const
corrected transverse momentum
Definition: PhysicsObject.h:55
static const int nPtBins
Definition: binnings.h:39
string isMC
Definition: Ntupliser_cfg.py:59
const float threshold
Definition: sigmoid.h:14
def inputs
Definition: jercExample.py:118
DAS::FourVector match(const DAS::FourVector &jet, const std::vector< DAS::FourVector > *hltJets)
Definition: match.h:7
Generic exception for problematic event (during event loop).
Definition: exceptions.h:63
ROOT::Math::LorentzVector< ROOT::Math::PtEtaPhiM4D< float > > FourVector
Definition: PhysicsObject.h:15
static const int nPtJERCbins
Definition: common.h:18
float GetTriggerEfficiency(int trigger, TH1 *h, STREAM &Stream, float from, float minEff)
Definition: sigmoid.h:101
@ CUTOFF
apply a selection on the weight
Definition: getSumWeights.cc:30
float getPrescale(Trigger *trigger, size_t indx)
Definition: getTriggerCurves.cc:94
Definition: applyJERsmearing.cc:41
static const int nYbins
Definition: binnings.h:38
float GetX(TF1 *f)
Definition: sigmoid.h:20
static const std::vector< TString > yBins
Definition: binnings.h:44
static const int nAbsEtaBins
Definition: common.h:23