|
DAS
3.0
Das Analysis System
|
|
void | applyJERsmearing (const vector< fs::path > &inputs, const fs::path &output, const pt::ptree &config, const int steering, const DT::Slice slice={1, 0}) |
|
void | applyJEScorrections (const vector< fs::path > inputs, const fs::path output, const pt::ptree &config, const int steering, const DT::Slice slice={1, 0}) |
|
std::vector< double > | getBinning (int nBins, float first, float last) |
|
void | assertValidBinning (const std::vector< double > &v) |
|
std::vector< float > | GetLogBinning (float minpt, float maxpt, int nbins) |
|
std::string | getAlgo (const Darwin::Tools::MetaInfo &metainfo) |
|
void | FitResolution (TDirectory *dir, unique_ptr< TH1 > h, const int steering) |
|
void | loopDirsFromFitResponse (TDirectory *dIn, TDirectory *dOut, const int steering) |
|
void | fitJetResolution (const fs::path &input, const fs::path &output, const pt::ptree &config, const int steering) |
|
vector< double > | GetMergedBinning (TH1 *h, const int threshold=30) |
|
pair< float, float > | findDLogExtrema (const unique_ptr< TH1 > &DLog, const double mu, const pair< float, float > Range) |
|
double | round_to (double value, double precision=1.0) |
|
TH1 * | CumulativeResponse (TH1 *res1D) |
|
void | FitResponseByBin (TDirectory *dir, unique_ptr< TH2 > res2D, const int steering) |
|
void | loopDirsFromGetResponse (TDirectory *dIn, TDirectory *dOut, const int steering, const DT::Slice slice) |
|
void | fitJetResponse (const fs::path &input, const fs::path &output, const pt::ptree &config, const int steering, const DT::Slice slice={1, 0}) |
|
void | getJetResponse (const vector< fs::path > &inputs, const fs::path &output, const pt::ptree &config, const int steering, const DT::Slice slice={1, 0}) |
|
void | getJMEtable (const fs::path input, const fs::path output, const pt::ptree &config, const int steering) |
|
void | ProcessVariations (const vector< TH3 * > &variations, TDirectory &dOut) |
|
void | loopDirsFromGetBalance (TDirectory *dIn, TDirectory *dOut) |
|
void | getPtAveBalance (const fs::path &input, const fs::path &output, const pt::ptree &config, const int steering) |
|
template<typename Jet > |
bool | DijetSelection (const std::vector< Jet > *jets, int iJES=0, const double alpha=0.3) |
|
vector< TString > | GetScaleVariations (const DT::MetaInfo &metainfo) |
|
void | getPtBalance (const vector< fs::path > inputs, const fs::path output, const pt::ptree &config, const int steering, const DT::Slice slice={1, 0}) |
|
|
static const std::vector< double > | pt_JERC_edges = {15, 17, 20, 23, 27, 30, 35, 40, 45, 57, 72, 90, 120, 150, 200, 300, 400, 550, 750, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500, 7000, 7500, 8000, 8500, 9000, 9500} |
|
static const int | nPtJERCbins = pt_JERC_edges.size()-1 |
|
static const std::vector< double > | abseta_edges = { 0.000, 0.261, 0.522, 0.783, 1.044, 1.305, 1.566, 1.740, 1.930, 2.043, 2.172, 2.322, 2.500, 2.650, 2.853, 2.964, 3.139, 3.489, 3.839, 5.191 } |
|
static const int | nAbsEtaBins = abseta_edges.size()-1 |
|
static const std::vector< TString > | absetaBins = MakeTitle(abseta_edges, "|#eta|", false, true, [](double v) { return Form("%.3f", v);}) |
|
static const std::map< int, std::vector< double > > | rho_edges |
|
static const std::map< int, int > | nRhoBins |
|
static const std::map< int, std::vector< TString > > | rhoBins |
|
static const std::vector< double > | eta_unc_edges = {-5.4, -5.0, -4.4, -4.0, -3.5, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0 , 0.2 , 0.4 , 0.6 , 0.8 , 1.0 , 1.2 , 1.4 , 1.6 , 1.8 , 2.0 , 2.2 , 2.4 , 2.6 , 2.8 , 3.0, 3.5 , 4.0 , 4.4 , 5.0 , 5.4} |
|
static const int | nEtaUncBins = eta_unc_edges.size()-1 |
|
static const std::vector< std::string > | JES_variations {"AbsoluteStat", "AbsoluteScale", "AbsoluteMPFBias", "Fragmentation", "SinglePionECAL", "SinglePionHCAL", "FlavorQCD", "RelativeJEREC1", "RelativeJEREC2", "RelativeJERHF", "RelativePtBB", "RelativePtEC1", "RelativePtEC2", "RelativePtHF", "RelativeBal", "RelativeSample", "RelativeFSR", "RelativeStatFSR", "RelativeStatEC", "RelativeStatHF", "PileUpDataMC", "PileUpPtRef", "PileUpPtBB", "PileUpPtEC1", "PileUpPtEC2", "PileUpPtHF"} |
|
static const float | w = 0.8 |
|
static const auto | deps = numeric_limits<double>::epsilon() |
|
◆ applyJERsmearing()
void DAS::JetEnergy::applyJERsmearing |
( |
const vector< fs::path > & |
inputs, |
|
|
const fs::path & |
output, |
|
|
const pt::ptree & |
config, |
|
|
const int |
steering, |
|
|
const DT::Slice |
slice = {1,0} |
|
) |
| |
Get JER smearing corrections in the form of factors to store in the scales
member of RecJet
.
- Todo:
- investigate JER uncertainty breakdown (see Core#35)
- Todo:
- fix in case of offset (e.g. JES applied on MC)
- Parameters
-
inputs | input ROOT files (n-tuples) |
output | name of output ROOT files (n-tuples) |
config | config file from `DTOptions` |
steering | steering parameters from `DTOptions` |
slice | slices for running |
54 cout << __func__ <<
' ' << slice <<
" start" << endl;
58 auto tOut = unique_ptr<TTree>(tIn->CloneTree(0));
62 auto isMC = metainfo.Get<
bool>(
"flags",
"isMC");
63 auto R = metainfo.Get<
int>(
"flags",
"R");
64 if (!
isMC) BOOST_THROW_EXCEPTION(
DE::BadInput(
"Only MC may be used as input.",
65 make_unique<TFile>(
inputs.front().c_str() )) );
66 JMEmatching<vector<RecJet>, vector<GenJet>>::maxDR = (R/10.)/2;
68 GenEvent * genEvt =
nullptr;
69 RecEvent * recEvt =
nullptr;
70 PileUp * pu =
nullptr;
71 tIn->SetBranchAddress(
"genEvent", &genEvt);
72 tIn->SetBranchAddress(
"recEvent", &recEvt);
73 tIn->SetBranchAddress(
"pileup", &pu);
75 vector<GenJet> * genJets =
nullptr;
76 vector<RecJet> * recJets =
nullptr;
77 tIn->SetBranchAddress(
"genJets", &genJets);
78 tIn->SetBranchAddress(
"recJets", &recJets);
80 const auto& tables =
config.get<fs::path>(
"corrections.JER.tables");
81 metainfo.Set<fs::path>(
"corrections",
"JER",
"tables", tables);
82 if (!fs::exists(tables))
83 BOOST_THROW_EXCEPTION( fs::filesystem_error(
"File does not exists.",
84 tables, make_error_code(errc::no_such_file_or_directory)) );
85 const auto tag =
config.get<
string>(
"corrections.JER.tag");
86 metainfo.Set<
string>(
"corrections",
"JER",
"tag", tag);
87 const auto& core_width =
config.get<
float>(
"corrections.JER.core_width");
89 metainfo.Set<
float>(
"corrections",
"JER",
"core_width", core_width);
92 ControlPlots raw(
"raw");
93 vector<ControlPlots> calib { ControlPlots(
"nominal") };
95 const bool applySyst = steering &
DT::syst;
96 vector<string> vars {
"nom"};
99 metainfo.Set<
string>(
"variations", RecJet::ScaleVar,
"JER" +
SysDown);
100 metainfo.Set<
string>(
"variations", RecJet::ScaleVar,
"JER" +
SysUp);
102 calib.push_back(ControlPlots(
"JER" +
SysDown));
103 calib.push_back(ControlPlots(
"JER" +
SysUp));
105 vars.push_back(
"up");
106 vars.push_back(
"down");
110 auto cset = correction::CorrectionSet::from_file(tables.string());
112 string keySF = tag +
"_ScaleFactor_AK" + to_string(R < 6 ? 4 : 8) +
"PF" +
algo,
113 keyJER = tag +
"_PtResolution_AK" + to_string(R < 6 ? 4 : 8) +
"PF" +
algo;
114 correction::Correction::Ref SF, JER;
116 SF =
cset->at(keySF );
117 JER =
cset->at(keyJER);
119 catch (out_of_range) {
120 BOOST_THROW_EXCEPTION( invalid_argument(
"`" + keySF +
"` or `" + keyJER +
121 "` could not be found in " + tables.string()) );
125 auto getSFs = [&SF,&vars](
const RecJet&
recjet) {
127 for (
const string var: vars)
128 sfs.push_back(SF->evaluate({recjet.p4.Eta(), var}));
131 auto applySFs = [applySyst](RecJet&
recjet,
const vector<float>& sfs) {
134 scale *= sfs.front();
141 auto getJER = [pu,&JER](
const RecJet&
recjet) {
145 for (
DT::Looper looper(tIn, slice); looper(); ++looper) {
148 cout <<
"===============" << endl;
150 raw(*genJets, genEvt->weights.front());
151 raw(*recJets, genEvt->weights.front() * recEvt->weights.front());
153 cout <<
"Running matching" << endl;
154 JMEmatching matching(*recJets, *genJets);
155 auto fake_its = matching.fake_its;
157 cout <<
"Applying scaling smearing for jets matched in the core of the response" << endl;
158 for (
const auto& [rec_it, gen_it]: matching.match_its) {
159 cout <<
"---------------" << endl;
161 float genpt = gen_it->p4.Pt(),
162 recpt = rec_it->CorrPt();
165 resolution = getJER(*rec_it);
167 cout <<
"|- genpt = " << genpt <<
'\n'
168 <<
"|- recpt = " << recpt <<
'\n'
169 <<
"|- response = " <<
response <<
'\n'
170 <<
"|- resolution = " << resolution << endl;
172 vector<float> sfs = getSFs(*rec_it);
173 if (abs(
response - 1) > core_width * resolution) {
174 cout <<
"|- match in the tail" << endl;
175 fake_its.push_back(rec_it);
178 cout <<
"|- match in the core" << endl;
180 for (
float&
sf: sfs) {
182 sf = max(0.
f, 1+(
sf-1)*(recpt-genpt)/recpt);
183 cout <<
" -> " <<
sf << endl;
186 cout <<
"|- applying SFs" << endl;
187 applySFs(*rec_it, sfs);
190 cout <<
"Applying stochastic smearing for all other jets "
191 "(either unmatched, or matched in the tails of the response)" << endl;
192 for (
auto& fake_it: fake_its) {
194 float resolution = getJER(*fake_it);
195 normal_distribution<float> d{0,resolution};
196 static mt19937 m_random_generator(metainfo.Seed<20394242>(slice));
197 float response = d(m_random_generator);
199 cout <<
"|- recpt = " << fake_it->CorrPt() <<
'\n'
200 <<
"|- response = " <<
response <<
'\n'
201 <<
"|- resolution = " << resolution << endl;
203 vector<float> sfs = getSFs(*fake_it);
204 for (
float&
sf: sfs) {
207 cout <<
" -> " <<
sf << endl;
210 cout <<
"|- applying SFs" << endl;
212 applySFs(*fake_it, sfs);
215 cout <<
"Sorting by descending pt" << endl;
216 sort(recJets->begin(), recJets->end(),
pt_sort);
218 for (
size_t i = 0; i < calib.size(); ++i) {
219 calib.at(i)(*genJets, genEvt->weights.front());
220 calib.at(i)(*recJets, genEvt->weights.front() * recEvt->weights.front(), i);
223 cout <<
"Filling" << endl;
224 if (steering &
DT::fill) tOut->Fill();
227 metainfo.Set<
bool>(
"git",
"complete",
true);
230 raw.Write(fOut.get());
234 cout << __func__ <<
' ' << slice <<
" end" << endl;
◆ applyJEScorrections()
void DAS::JetEnergy::applyJEScorrections |
( |
const vector< fs::path > |
inputs, |
|
|
const fs::path |
output, |
|
|
const pt::ptree & |
config, |
|
|
const int |
steering, |
|
|
const DT::Slice |
slice = {1,0} |
|
) |
| |
Apply JES corrections to data and MC *n*tuples, as well as uncertainties in data (all sources are considered separately)
- Todo:
- CorrPt?
- Parameters
-
inputs | input ROOT files (n-tuples) |
output | name of output root file containing the histograms |
config | config file from `DTOptions` |
steering | steering parameters from `DTOptions` |
slice | slices for running |
44 cout << __func__ <<
' ' << slice <<
" start" << endl;
48 auto tOut = unique_ptr<TTree>(tIn->CloneTree(0));
52 auto isMC = metainfo.Get<
bool>(
"flags",
"isMC");
53 auto R = metainfo.Get<
int>(
"flags",
"R");
55 RecEvent * recEvt =
nullptr;
56 GenEvent * genEvt =
nullptr;
57 PileUp * pu =
nullptr;
58 tIn->SetBranchAddress(
"recEvent", &recEvt);
60 tIn->SetBranchAddress(
"genEvent", &genEvt);
61 tIn->SetBranchAddress(
"pileup", &pu);
63 vector<RecJet> * recJets =
nullptr;
64 tIn->SetBranchAddress(
"recJets", &recJets);
66 const auto tables =
config.get<fs::path>(
"corrections.JES.tables");
67 metainfo.Set<fs::path>(
"corrections",
"JES",
"tables", tables);
68 if (!fs::exists(tables))
69 BOOST_THROW_EXCEPTION( fs::filesystem_error(
"File does not exists.",
70 tables, make_error_code(errc::no_such_file_or_directory)) );
71 const auto tag =
config.get<
string>(
"corrections.JES.tag");
72 metainfo.Set<
string>(
"corrections",
"JES",
"tag", tag);
75 ControlPlots raw(
"raw");
76 vector<ControlPlots> calib { ControlPlots(
"nominal") };
78 const bool applySyst = steering &
DT::syst;
82 metainfo.Set<
string>(
"variations", RecJet::ScaleVar,
source +
SysDown);
83 metainfo.Set<
string>(
"variations", RecJet::ScaleVar,
source +
SysUp);
90 auto cset = correction::CorrectionSet::from_file(tables.string());
92 string key = tag +
"_L1L2L3Res_AK" + to_string(R < 6 ? 4 : 8) +
"PF" +
algo;
93 correction::CompoundCorrection::Ref nomSF =
cset->compound().at(
key);
94 vector<correction::Correction::Ref> varSFs;
97 key = tag +
'_' +
source +
"_AK" + to_string(R < 6 ? 4 : 8) +
"PF" +
algo;
98 varSFs.push_back(
cset->at(
key));
101 for (
DT::Looper looper(tIn, slice); looper(); ++looper) {
105 double weight = recEvt->weights.front();
111 for (
auto& recJet: *recJets) {
114 if (recJet.scales.size() != 1 || recJet.scales.front() != 1)
118 auto corr = nomSF->evaluate({recJet.area, recJet.p4.Eta(), recJet.p4.Pt(), pu->rho});
119 cout << recJet.p4.Pt() <<
' ' << corr <<
'\n';
120 recJet.scales.front() = corr;
122 if (!applySyst)
continue;
126 for (
const correction::Correction::Ref& varSF: varSFs) {
127 auto var = varSF->evaluate({recJet.p4.Eta(), recJet.p4.Pt()});
128 recJet.scales.push_back(corr*(1-var));
129 recJet.scales.push_back(corr*(1+var));
135 for (
size_t i = 0; i < calib.size(); ++i)
136 calib.at(i)(*recJets,
weight, i);
138 sort(recJets->begin(), recJets->end(),
pt_sort);
139 if (steering &
DT::fill) tOut->Fill();
142 metainfo.Set<
bool>(
"git",
"complete",
true);
145 raw.Write(fOut.get());
149 cout << __func__ <<
' ' << slice <<
" end" << endl;
◆ assertValidBinning()
void DAS::JetEnergy::assertValidBinning |
( |
const std::vector< double > & |
v | ) |
|
|
inline |
60 for (
size_t i = 1; i<v.size(); ++i) {
61 if (v[i] > v[i-1])
continue;
62 std::cerr << i <<
' ' << v[i] <<
' ' << v[i-1] <<
'\n';
◆ CumulativeResponse()
TH1* DAS::JetEnergy::CumulativeResponse |
( |
TH1 * |
res1D | ) |
|
Creating cumulative response histogram. Given a response 1D histogram, it adds to a bin the content of all previous bins.
309 const int NptBins = res1D->GetNbinsX();
310 for (
int n = 1; n <= NptBins; ++n) {
311 cont+=res1D->GetBinContent(n);
312 res1D->SetBinContent(n, cont);
◆ DijetSelection()
bool DAS::JetEnergy::DijetSelection |
( |
const std::vector< Jet > * |
jets, |
|
|
int |
iJES = 0 , |
|
|
const double |
alpha = 0.3 |
|
) |
| |
Apply dijet topology selection independently from the level.
- Parameters
-
jets | full jet vector |
iJES | JES variation index (only for rec-level) |
alpha | reject significant extra jets |
51 if (
jets->size() < 2)
return false;
54 using ROOT::Math::VectorUtil::DeltaPhi;
55 if (DeltaPhi(
jets->at(0).p4,
jets->at(1).p4) < 2.7)
return false;
58 if (std::abs(
jets->at(0).p4.Eta()) >= 3.0 ||
59 std::abs(
jets->at(1).p4.Eta()) >= 3.0)
return false;
62 if (
jets->size() > 2) {
63 if constexpr (is_same<Jet,RecJet>()) {
64 const auto pt0 =
jets->at(0).CorrPt(iJES),
65 pt1 =
jets->at(1).CorrPt(iJES),
66 pt2 =
jets->at(2).CorrPt(iJES);
67 if (pt2 > alpha*(pt0 + pt1)/2)
return false;
70 const auto pt0 =
jets->at(0).p4.Pt(),
71 pt1 =
jets->at(1).p4.Pt(),
72 pt2 =
jets->at(2).p4.Pt();
73 if (pt2 > alpha*(pt0 + pt1)/2)
return false;
◆ findDLogExtrema()
pair<float,float> DAS::JetEnergy::findDLogExtrema |
( |
const unique_ptr< TH1 > & |
DLog, |
|
|
const double |
mu, |
|
|
const pair< float, float > |
Range |
|
) |
| |
Find the positions of the extrema, starting from the mean and within a given range (to avoid regions with too large fluctuations).
80 const int m = DLog->FindBin(mu);
84 for (
int i = m; i >= DLog->FindBin(Range.first); --i)
85 if (DLog->GetBinContent(i) > DLog->GetBinContent(imax)) imax = i;
86 float x1 = DLog->GetBinLowEdge(imax+1);
90 for (
int i = m; i <= DLog->FindBin(Range.second); ++i)
91 if (DLog->GetBinContent(i) < DLog->GetBinContent(imin)) imin = i;
92 float x2 = DLog->GetBinLowEdge(imin);
◆ fitJetResolution()
void DAS::JetEnergy::fitJetResolution |
( |
const fs::path & |
input, |
|
|
const fs::path & |
output, |
|
|
const pt::ptree & |
config, |
|
|
const int |
steering |
|
) |
| |
Fit resolution curves from fitJetResponse
- Parameters
-
input | input ROOT file (histograms) |
output | name of output ROOT (histograms) |
config | config file from `DTOptions` |
steering | steering parameters from `DTOptions` |
235 cout << __func__ <<
" start" << endl;
237 auto fIn = make_unique<TFile>(
input .c_str(),
"READ"),
238 fOut = make_unique<TFile>(output.c_str(),
"RECREATE");
241 cout << __func__ <<
" stop" << endl;
◆ fitJetResponse()
void DAS::JetEnergy::fitJetResponse |
( |
const fs::path & |
input, |
|
|
const fs::path & |
output, |
|
|
const pt::ptree & |
config, |
|
|
const int |
steering, |
|
|
const DT::Slice |
slice = {1,0} |
|
) |
| |
Fit response distributions from getJetResponse
- Parameters
-
input | input ROOT file (histograms) |
output | name of output ROOT (histograms) |
config | config file from `DTOptions` |
steering | steering parameters from `DTOptions` |
slice | number and index of slice |
512 cout << __func__ <<
' ' << slice <<
" start" << endl;
514 auto fIn = make_unique<TFile>(
input .c_str(),
"READ"),
515 fOut = make_unique<TFile>(output.c_str(),
"RECREATE");
518 cout << __func__ <<
' ' << slice <<
" stop" << endl;
◆ FitResolution()
void DAS::JetEnergy::FitResolution |
( |
TDirectory * |
dir, |
|
|
unique_ptr< TH1 > |
h, |
|
|
const int |
steering |
|
) |
| |
Fit the resolution obtained from fitJetResponse
in a given eta/rho bin.
- Todo:
- parameters in bins of eta (and rho/mu?)
--> one should probably give the directory with all eta bins as input
172 TString stdPrint = h->GetTitle();
173 stdPrint.ReplaceAll(TString( h->GetName() ),
"");
174 cout << h->GetName() <<
'\t' << stdPrint << endl;
177 ResolutionFit res(h, cout);
◆ FitResponseByBin()
void DAS::JetEnergy::FitResponseByBin |
( |
TDirectory * |
dir, |
|
|
unique_ptr< TH2 > |
res2D, |
|
|
const int |
steering |
|
) |
| |
Projection 2D histograms onto 1D histograms and fit response
Fit is currently performed in 3 stages:
- Fit the Gaussian core to get a better estimation of the mean and sigma.
- Extend the fit right range, transposing to a Single-Sided Crystal Ball fit, using the mean and sigma better define the fit parameters.
- Extend the fit left range, transposing to a Double-Sided Crystal Ball fit.
Fit iteratively on each stage by adjusting the fit range so that you minimize the amount of failed fits.
334 auto h_ptBins = unique_ptr<TH1>(
dynamic_cast<TH1*
>(res2D->ProjectionX(
"h_ptBins", 1, -1)) );
335 h_ptBins->GetXaxis()->SetTitle(
"p_{T}^{gen}");
338 map<TString, unique_ptr<TH1>> hists;
339 for (TString
name: {
"meanCore",
"sigmaCore",
343 "chi2ndf",
"Median"}) {
345 hists.insert( {
name, unique_ptr<TH1>(
dynamic_cast<TH1*
>( h_ptBins->Clone(
name) )) } );
346 hists[
name]->Reset();
348 hists[
name]->SetDirectory(
nullptr);
352 hists.insert( {
name, unique_ptr<TH1>(
dynamic_cast<TH1*
>( h_ptBins->Clone(
name) )) } );
353 hists[
name]->Reset();
355 hists[
name]->SetDirectory(
nullptr);
358 int Npt = res2D->GetXaxis()->GetNbins();
359 for (
int ptbin = 1; ptbin <= Npt; ++ptbin) {
360 double lowEdge = res2D->GetXaxis()->GetBinLowEdge(ptbin),
361 upEdge = res2D->GetXaxis()->GetBinUpEdge (ptbin);
362 const char * level = TString( res2D->GetXaxis()->GetTitle() ).Contains(
"gen") ?
"gen" :
"rec";
363 const char * hlt_level = TString( res2D->GetXaxis()->GetTitle() ).Contains(
"HLT") ?
"HLT" : level;
364 TString title = Form(
"%.0f < p_{T}^{%s} < %.0f", lowEdge, hlt_level, upEdge),
365 stdPrint = TString( res2D->GetTitle() );
366 stdPrint.ReplaceAll(
"zx projection",
"");
367 stdPrint.ReplaceAll(
")",
"");
368 stdPrint +=
", " + title +
")";
369 cout << stdPrint <<
def << endl;
372 auto original = unique_ptr<TH1>(
dynamic_cast<TH1*
>(res2D->ProjectionY(
"original", ptbin, ptbin)) );
373 if (original->GetEntries() < 100) {
374 cout <<
orange <<
"Skipped due to low number of events!" <<
def << endl;
379 auto h = unique_ptr<TH1>( original->Rebin(edges.size()-1,
"h", edges.data()) );
380 const char * h_title = TString( res2D->GetXaxis()->GetTitle() ).Contains(
"HLT") ?
"HLT bin low edge" :
"gen";
381 h->GetXaxis()->SetTitle(Form(
"#frac{p_{T}^{rec}}{p_{T}^{%s}}", h_title));
384 TDirectory * d_pt = dir->mkdir(Form(
"ptbin%d", ptbin), title);
387 h->SetDirectory(d_pt);
388 float normalisation = abs( h->Integral() );
389 h->Scale(1.
f/normalisation,
"width");
394 double probability[1] = {0.5};
395 h->GetQuantiles(nQuantiles, &median, probability);
397 TString hlt_title = Form(
"%.0f < p_{T}^{%s} < %.0f", lowEdge, hlt_level, upEdge);
400 auto hc_tmp =
dynamic_cast<TH1*
>( h->Clone(
"hc_tmp") );
402 hc->SetNameTitle(
"h_cumulative", hlt_title);
403 hc->SetDirectory(d_pt);
407 ResponseFit resp(h, cout);
409 hists.at(
"Lcore")->SetBinContent(ptbin, resp.p[ResponseFit::KL]);
410 hists.at(
"Rcore")->SetBinContent(ptbin, resp.p[ResponseFit::KR]);
416 TString suffix = resp.good() ?
"" :
"Fail";
419 hists.at(
"meanCore" + suffix)->SetBinContent(ptbin, resp.p[ResponseFit::MU]);
420 hists.at(
"meanCore" + suffix)->SetBinError (ptbin, resp.e[ResponseFit::MU]);
421 hists.at(
"sigmaCore" + suffix)->SetBinContent(ptbin, resp.p[ResponseFit::SIGMA]);
422 hists.at(
"sigmaCore" + suffix)->SetBinError (ptbin, resp.e[ResponseFit::SIGMA]);
424 hists.at(
"kLtail" + suffix)->SetBinContent(ptbin, resp.p[ResponseFit::KL]);
425 hists.at(
"kLtail" + suffix)->SetBinError (ptbin, resp.e[ResponseFit::KL]);
426 hists.at(
"nLtail" + suffix)->SetBinContent(ptbin, resp.p[ResponseFit::NL]);
427 hists.at(
"nLtail" + suffix)->SetBinError (ptbin, resp.e[ResponseFit::NL]);
428 hists.at(
"kRtail" + suffix)->SetBinContent(ptbin, resp.p[ResponseFit::KR]);
429 hists.at(
"kRtail" + suffix)->SetBinError (ptbin, resp.e[ResponseFit::KR]);
430 hists.at(
"nRtail" + suffix)->SetBinContent(ptbin, resp.p[ResponseFit::NR]);
431 hists.at(
"nRtail" + suffix)->SetBinError (ptbin, resp.e[ResponseFit::NR]);
433 hists.at(
"chi2ndf" + suffix)->SetBinContent(ptbin, resp.chi2ndf .value_or(0));
434 hists.at(
"chi2ndf" + suffix)->SetBinError (ptbin, resp.chi2ndfErr.value_or(0));
436 hists.at(
"Median" + suffix)->SetBinContent(ptbin, median);
440 TString title = res2D->GetTitle();
441 title.ReplaceAll(
"Response distribution",
"");
442 title.ReplaceAll(
"zx projection",
"");
443 for (
auto&& h: hists) {
444 h.second->SetDirectory(dir);
445 h.second->SetTitle(h.second->GetTitle() + title);
◆ getAlgo()
Determine from metainfo if CHS or PUPPI has been used to reconstruct the jets.
88 if (metainfo.
Find(
"flags",
"labels",
"CHS" ))
return "chs";
89 if (metainfo.
Find(
"flags",
"labels",
"PUPPI"))
return "puppi";
91 std::cerr <<
orange <<
"Couldn't identify CHS or PUPPI. Running default "
92 "CHS for Run 2 (PUPPI foir Run 3)\n" <<
def;
94 auto year = metainfo.
Get<
int>(
"flag",
"year");
95 if (
year > 2019)
return "puppi";
96 if (
year > 2014)
return "chs";
◆ getBinning()
std::vector<double> DAS::JetEnergy::getBinning |
( |
int |
nBins, |
|
|
float |
first, |
|
|
float |
last |
|
) |
| |
|
inline |
51 std::vector<double>
bins(nBins+1);
52 for(
int i = 0; i <= nBins; ++i)
53 bins[i] = first + ((last-first)/nBins) * i;
◆ getJetResponse()
void DAS::JetEnergy::getJetResponse |
( |
const vector< fs::path > & |
inputs, |
|
|
const fs::path & |
output, |
|
|
const pt::ptree & |
config, |
|
|
const int |
steering, |
|
|
const DT::Slice |
slice = {1,0} |
|
) |
| |
Get JER differential resolution and balance.
- Todo:
- with gen level weight too?
- Todo:
- remove upper boundaries from titles of last bins
- 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 |
50 cout << __func__ <<
' ' << slice <<
" start" << endl;
54 auto tOut = unique_ptr<TTree>(tIn->CloneTree(0));
58 auto isMC = metainfo.Get<
bool>(
"flags",
"isMC");
60 BOOST_THROW_EXCEPTION(
DE::BadInput(
"Only MC may be used as input.", metainfo) );
62 const auto R = metainfo.Get<
int>(
"flags",
"R");
64 JMEmatching<>::maxDR = R/10./2.;
65 cout <<
"Radius for matching: " << JMEmatching<>::maxDR << endl;
67 RecEvent * rEv =
nullptr;
68 tIn->SetBranchAddress(
"recEvent", &rEv);
69 const auto hiPU =
config.get<
bool>(
"skims.pileup");
70 PileUp * pileUp =
nullptr;
72 tIn->SetBranchAddress(
"pileup", &pileUp);
74 vector<RecJet> *
recjets =
nullptr;
75 vector<GenJet> *
genjets =
nullptr;
76 tIn->SetBranchAddress(
"recJets", &
recjets);
77 tIn->SetBranchAddress(
"genJets", &
genjets);
79 unique_ptr<TH3> inclResp =
makeRespHist(
"inclusive",
"JER");
80 vector<unique_ptr<TH3>> rhobinsResp,
83 const auto year = metainfo.Get<
int>(
"flags",
"year");
87 for (
int rhobin = 1; rhobin <=
nRhoBins.at(
year); ++rhobin) {
88 rhobinsResp.push_back(
makeRespHist( Form(
"rhobin%d", rhobin) ,
"JER") );
89 mubinsResp.push_back(
makeRespHist( Form(
"mubin%d", rhobin) ,
"JER") );
93 for (
DT::Looper looper(tIn, slice); looper(); ++looper) {
97 auto recWgt = rEv->weights.front();
98 optional<size_t> irho, imu;
100 static const size_t nrho =
static_cast<size_t>(
nRhoBins.at(
year));
101 for (irho = 0; pileUp->rho >
rho_edges.at(
year).at(*irho+1) && *irho < nrho; ++*irho);
105 static const size_t imuMax = mubinsResp.size()-1;
106 imu =
static_cast<size_t>(pileUp->GetTrPU())/10;
107 *imu = min(*imu,imuMax);
113 matching.match_its.resize(min(matching.match_its.size(),3lu));
115 for (
auto& [rec_it,gen_it]: matching.match_its) {
116 auto ptrec = rec_it->CorrPt();
117 auto ptgen = gen_it->p4.Pt();
121 auto etarec = abs( rec_it->p4.Eta() );
123 inclResp->Fill(ptgen, etarec,
response, recWgt);
124 if (irho) rhobinsResp.at(*irho)->Fill(ptgen, etarec,
response, recWgt);
125 if (imu ) mubinsResp.at(*imu )->Fill(ptgen, etarec,
response, recWgt);
132 inclResp->SetDirectory(fOut.get());
133 inclResp->SetTitle(
"Response (inclusive)");
134 inclResp->Write(
"Response");
142 TDirectory * d_rho = fOut->mkdir(Form(
"rhobin%d", irho+1), title);
144 rhobinsResp.at(irho)->SetDirectory(fOut.get());
145 rhobinsResp.at(irho)->SetTitle(
"Response (" + title +
")");
146 rhobinsResp.at(irho)->Write(
"Response");
148 title = Form(
"%d < #mu < %d", irho*10, (irho+1)*10);
150 TDirectory * d_mu = fOut->mkdir(Form(
"mubin%d", irho+1), title);
152 mubinsResp.at(irho)->SetDirectory(fOut.get());
153 mubinsResp.at(irho)->SetTitle(
"Response (" + title +
")");
154 mubinsResp.at(irho)->Write(
"Response");
158 metainfo.Set<
bool>(
"git",
"complete",
true);
161 cout << __func__ <<
' ' << slice <<
" end" << endl;
◆ getJMEtable()
void DAS::JetEnergy::getJMEtable |
( |
const fs::path |
input, |
|
|
const fs::path |
output, |
|
|
const pt::ptree & |
config, |
|
|
const int |
steering |
|
) |
| |
Obtain corrections and uncertainties in ROOT format for plotting and comparison.
- Todo:
- identify algo
- Todo:
- check binning
- Parameters
-
input | JetMET JES tables in JSON format |
output | name of output root file |
config | config file from `DTOptions` |
steering | steering parameters from `DTOptions` |
40 cout << __func__ <<
" start" << endl;
44 auto R =
config.get<
int>(
"flags.R");
47 cout << R <<
' ' <<
year <<
' ' <<
algo << endl;
49 const auto tag =
config.get<
string>(
"corrections.JES.tag"),
50 level =
config.get<
string>(
"corrections.JES.level");
51 string key = tag +
"_" + level +
"_AK" + to_string(R) +
"PF" +
algo;
54 auto cset = correction::CorrectionSet::from_file(
input.string());
55 correction::Correction::Ref
sf;
59 catch (std::out_of_range& e) {
60 BOOST_THROW_EXCEPTION( std::invalid_argument(
"Nothing corresponding to that key") );
63 cout <<
"Declaring histogram" << endl;
65 map<string, correction::Variable::Type> named_inputs;
66 if (level ==
"L1FastJet" || level ==
"PtResolution") {
67 h = make_unique<TH3D>(level.c_str(), level.c_str(),
72 named_inputs[
"JetA"] = M_PI * pow(R*0.1, 2);
74 else if (level ==
"L2Relative" || level ==
"L2L3Residual")
75 h = make_unique<TH2D>(level.c_str(), level.c_str(),
78 else if (level ==
"ScaleFactor") {
79 h = make_unique<TH1D>(level.c_str(), level.c_str(),
81 named_inputs[
"systematic"] =
"nom";
84 h = make_unique<TH2D>(level.c_str(), level.c_str(),
88 cout <<
"dim = " << h->GetDimension() << endl;
89 for (
int etabin = 1; etabin <= h->GetNbinsX(); ++etabin)
90 for (
int ptbin = 1; ptbin <= h->GetNbinsY(); ++ ptbin)
91 for (
int rhobin = 1; rhobin <= h->GetNbinsZ(); ++rhobin) {
93 named_inputs[
"JetEta"] = h->GetXaxis()->GetBinCenter(etabin);
94 named_inputs[
"JetPt" ] = h->GetYaxis()->GetBinCenter( ptbin);
95 named_inputs[
"Rho" ] = h->GetZaxis()->GetBinCenter(rhobin);
98 vector<correction::Variable::Type>
inputs;
99 for (
const correction::Variable&
input:
sf->inputs())
103 double value =
sf->evaluate(
inputs);
105 cout << setw(5) << ptbin << setw(5) << etabin << setw(5) << rhobin << setw(15) << value << endl;
107 if (level ==
"L1FastJet")
108 h->SetBinContent(etabin, ptbin, rhobin, value);
109 else if (level ==
"ScaleFactor")
110 h->SetBinContent(etabin, value);
112 h->SetBinContent(etabin, ptbin, value);
116 cout << __func__ <<
" end" << endl;
◆ GetLogBinning()
std::vector<float> DAS::JetEnergy::GetLogBinning |
( |
float |
minpt, |
|
|
float |
maxpt, |
|
|
int |
nbins |
|
) |
| |
|
inline |
Make equidistant binning in log pt.
- Todo:
- this accumulates imprecision --> improve
74 std::vector<float> edges;
79 std::cout << edges.size() << std::endl;
◆ GetMergedBinning()
vector<double> DAS::JetEnergy::GetMergedBinning |
( |
TH1 * |
h, |
|
|
const int |
threshold = 30 |
|
) |
| |
Provide a new binning ensuring a sufficient number of entries in each bin to assume Gaussian uncertainties.
For a gaussian distribution, as it is assumed for the number of events in each bin, the error is given as sqrt(n) where n the number of events in the bin. Assuming both the bin content and error have been normalised, by taking the division of the (BinContent/BinError)^2 ~ n, one can estimate the number of events in that bin.
There is no special treatment for negative weights, as the samples used to develop the code have no such weight. A warning is however displayed in case negative bins are found.
51 const int N = h->GetNbinsX();
52 vector<double> edges(1,0);
55 for (
int i = 1; i <= N; ++i) {
56 auto content = h->GetBinContent(i);
57 if (content == 0)
continue;
60 << h->GetName() <<
def <<
'\n';
61 auto error = h->GetBinError(i);
62 sum += pow(content/error,2);
65 edges.push_back(h->GetBinLowEdge(i+1));
67 if (edges.back() != h->GetBinLowEdge(N+1))
68 edges.push_back(h->GetBinLowEdge(N+1));
◆ getPtAveBalance()
void DAS::JetEnergy::getPtAveBalance |
( |
const fs::path & |
input, |
|
|
const fs::path & |
output, |
|
|
const pt::ptree & |
config, |
|
|
const int |
steering |
|
) |
| |
This function iterate over the histograms produced by getPtBalance
and produces the the momentum balance histograms in bins of ptave and eta. It calls the loopDir()
function defined above.
- Todo:
- use config and steering (e.g. for verbosity)
- Parameters
-
input | input ROOT file (histograms) |
output | name of output ROOT (histograms) |
config | config file from `DTOptions` |
steering | steering parameters from `DTOptions` |
235 auto fIn = make_unique<TFile>(
input .c_str(),
"READ"),
236 fOut = make_unique<TFile>(output.c_str(),
"RECREATE");
◆ getPtBalance()
void DAS::JetEnergy::getPtBalance |
( |
const vector< fs::path > |
inputs, |
|
|
const fs::path |
output, |
|
|
const pt::ptree & |
config, |
|
|
const int |
steering, |
|
|
const DT::Slice |
slice = {1,0} |
|
) |
| |
Get Pt balance.
- Parameters
-
inputs | input ROOT files (n-tuples) |
output | name of output root file containing the histograms |
config | config file from `DTOptions` |
steering | steering parameters from `DTOptions` |
slice | slices for running |
174 cout << __func__ <<
' ' << slice <<
" start" << endl;
178 auto tOut = unique_ptr<TTree>(tIn->CloneTree(0));
182 auto isMC = metainfo.Get<
bool>(
"flags",
"isMC");
184 RecEvent * rEv =
nullptr;
185 GenEvent * gEv =
nullptr;
186 tIn->SetBranchAddress(
"recEvent", &rEv);
188 tIn->SetBranchAddress(
"genEvent", &gEv);
189 vector<RecJet> *
recjets =
nullptr;
190 vector<GenJet> *
genjets =
nullptr;
191 tIn->SetBranchAddress(
"recJets", &
recjets);
193 tIn->SetBranchAddress(
"genJets", &
genjets);
197 : vector<TString>{
"nominal"};
200 vector<BalanceHists<RecJet>> recBalances;
201 recBalances.emplace_back(
"rec_barrel_vs_any", variations);
204 vector<BalanceHists<GenJet>> genBalances;
206 genBalances.emplace_back(
"gen_barrel_vs_any", vector<TString>{
"nominal"});
208 TRandom3 r3(metainfo.Seed<39856>(slice));
209 for (
DT::Looper looper(tIn, slice); looper(); ++looper) {
213 auto gw =
isMC ? gEv->weights.front() : Weight{1.,0},
214 rw = rEv->weights.front();
217 auto r = r3.Uniform();
221 if (DijetSelection<RecJet>(
recjets))
222 for (
auto bal: recBalances)
227 if (DijetSelection<GenJet>(
genjets))
228 for (
auto bal: genBalances)
233 for (
auto p: recBalances)
p.Write(fOut.get());
234 for (
auto p: genBalances)
p.Write(fOut.get());
237 metainfo.Set<
bool>(
"git",
"complete",
true);
240 cout << __func__ <<
' ' << slice <<
" stop" << endl;
◆ GetScaleVariations()
vector<TString> DAS::JetEnergy::GetScaleVariations |
( |
const DT::MetaInfo & |
metainfo | ) |
|
147 vector<TString> variations{
"nominal"};
148 const TList * groupContents = metainfo.
List(
"variations", RecJet::ScaleVar);
150 BOOST_THROW_EXCEPTION( invalid_argument(groupContents->GetName()) );
152 for (
const TObject * obj: *groupContents) {
153 const auto os =
dynamic_cast<const TObjString*
>(obj);
154 if (!os) BOOST_THROW_EXCEPTION( invalid_argument(obj->GetName()) );
155 TString s = os->GetString();
156 s.ReplaceAll(
SysUp,
"");
159 variations.push_back(os->GetString());
◆ loopDirsFromFitResponse()
void DAS::JetEnergy::loopDirsFromFitResponse |
( |
TDirectory * |
dIn, |
|
|
TDirectory * |
dOut, |
|
|
const int |
steering |
|
) |
| |
Copy directory structure. Given an input directory dIn
recursively loop over all directory hierarchy/contents and reproduce it in the directory dOut
of the output file. For each TH1
instance found containing the resolution, perform a NSC fit by calling FitResolution()
function.
198 for (
const auto&& obj: *(dIn->GetListOfKeys())) {
199 auto const key =
dynamic_cast<TKey*
>(obj);
200 if (
key->IsFolder() ) {
201 auto ddIn =
dynamic_cast<TDirectory*
>(
key->ReadObj() );
202 if ( TString( ddIn->GetName() ).Contains(
"ptbin") )
continue;
203 TDirectory * ddOut = dOut->mkdir(ddIn->GetName(), ddIn->GetTitle());
205 cout <<
bold << ddIn->GetPath() <<
def << endl;
209 else if ( TString(
key->ReadObj()->GetName() ).Contains(
"sigmaCore") ) {
210 auto res = unique_ptr<TH1>(
dynamic_cast<TH1*
>(
key->ReadObj()) );
211 res->SetDirectory(dOut);
215 if ( TString(res->GetName()).Contains(
"Fail") )
continue;
220 else cout <<
orange <<
"Ignoring " <<
key->ReadObj()->GetName() <<
" of `"
221 <<
key->ReadObj()->ClassName() <<
"` type" <<
def << endl;
223 cout <<
def << flush;
◆ loopDirsFromGetBalance()
void DAS::JetEnergy::loopDirsFromGetBalance |
( |
TDirectory * |
dIn, |
|
|
TDirectory * |
dOut |
|
) |
| |
This function is called by getPtAveBalance()
. Recusively iterates over the internal structure of a file/directory and each it fins a serie of TH3 in the file, it interpret it as the many variations of the jet energy balance and us it to calculate the mean of the balance and also the balance curves in bins of pt and eta.
NOTE: additional remark on the implementation: Once the TH3 representing the binned in pt_balance, eta, y (presumably in the order (x, y, z), the pt_balance is projected into a 1-D histogram for each bin of rapidity and pt_ave (this done for each of the variations). For each bin of rapidity, the mean of the pt_balance is computed (see formula in th comments of ProcessVariations()
the standard deviations from the balance are calculated from the statistical uncertainities and from the variations (presumably the variations of the JES).
188 vector<TH3*> variations;
189 for (
const auto&& obj: *(dIn->GetListOfKeys())) {
190 auto const key =
dynamic_cast<TKey*
>(obj);
191 if (
key->IsFolder() ) {
192 auto ddIn =
dynamic_cast<TDirectory*
>(
key->ReadObj() );
193 if (ddIn ==
nullptr) {
194 cerr <<
red <<
"ddIn = " << ddIn <<
'\n' <<
def;
197 TDirectory * ddOut = dOut->mkdir(ddIn->GetName(), ddIn->GetTitle());
199 cout <<
"creating directory " <<
bold << ddIn->GetPath() <<
normal << endl;
203 else if ( ( TString(
key->ReadObj()->ClassName() ).Contains(
"TH3") ) ) {
204 auto bal3D =
dynamic_cast<TH3*
>(
key->ReadObj() );
205 bal3D->SetDirectory(0);
206 variations.push_back(bal3D);
208 else cout <<
"Found " <<
orange <<
key->ReadObj()->GetName() <<
normal <<
".. Is of "
209 <<
underline <<
key->ReadObj()->ClassName() <<
normal <<
" type, ignoring it" << endl;
220 if (variations.size() > 0)
◆ loopDirsFromGetResponse()
void DAS::JetEnergy::loopDirsFromGetResponse |
( |
TDirectory * |
dIn, |
|
|
TDirectory * |
dOut, |
|
|
const int |
steering, |
|
|
const DT::Slice |
slice |
|
) |
| |
Copy directory structure. Given an input file dIn recursively loop over all directory hierarchy/contents and reproduce it in output file dOut. For each TH3 instance found containing the response perform a DCB fit by calling FitResponseByBin() function.
461 for (
const auto&& obj: *(dIn->GetListOfKeys())) {
462 auto const key =
dynamic_cast<TKey*
>(obj);
463 if (
key->IsFolder() ) {
464 auto ddIn =
dynamic_cast<TDirectory*
>(
key->ReadObj() );
465 if (ddIn ==
nullptr)
continue;
466 TDirectory * ddOut = dOut->mkdir(ddIn->GetName(), ddIn->GetTitle());
468 cout <<
bold << ddIn->GetPath() <<
def << endl;
472 else if ( TString(
key->ReadObj()->ClassName() ).Contains(
"TH3") ) {
474 auto hist3D = unique_ptr<TH3>(
dynamic_cast<TH3*
>(
key->ReadObj()) );
475 hist3D->SetDirectory(0);
476 bool isAbsEta = hist3D->GetYaxis()->GetBinLowEdge(1) >= 0;
477 TDirectory * ddOut = dOut->mkdir(
key->GetName(),
key->ReadObj()->GetTitle());
478 for (
int etabin = 1; etabin <= hist3D->GetNbinsY(); ++etabin) {
481 if (slice.second != ieta % slice.first)
continue;
483 float lowedge = hist3D->GetYaxis()->GetBinLowEdge(etabin),
484 upedge = hist3D->GetYaxis()->GetBinUpEdge (etabin);
485 TString title = isAbsEta ? Form(
"%.3f < |#eta| < %.3f", lowedge, upedge)
486 : Form(
"%.3f < #eta < %.3f" , lowedge, upedge);
487 hist3D->GetYaxis()->SetRange(etabin, etabin);
488 auto hist2D = unique_ptr<TH2>(
dynamic_cast<TH2*
>(hist3D->Project3D(
"ZX")) );
489 hist2D->SetTitle( TString( hist2D->GetTitle() ).ReplaceAll(
") ",
", " + title +
")") );
491 TDirectory * dddOut = ddOut->mkdir(Form(
"etabin%d", etabin), title);
492 cout <<
bold << dddOut->GetPath() <<
def << endl;
497 else cout <<
orange <<
"Ignoring " <<
key->ReadObj()->GetName() <<
" of `"
498 <<
key->ReadObj()->ClassName() <<
"` type" <<
def << endl;
◆ ProcessVariations()
void DAS::JetEnergy::ProcessVariations |
( |
const vector< TH3 * > & |
variations, |
|
|
TDirectory & |
dOut |
|
) |
| |
This function is called by loopDirsFromGetBalance()
. It takes as argument a vector of TH3 which presumabilly represents the transverse momentum balance ($p_{T}^{bal}$) histograms in bins of ($p_{T}^{bal}$, $p_{T}^{ave}$, $y_{probe}$) for different variations of the JES. This function project the pt_balance histogram in 1-D for each bin of $p_{T}^{ave}$ and $y_{probe}$. This function calculates the histogram of the mean value of the balance in bins of $p_{T}^{ave}$ for each bin, it calculates the incertainty bands deduced from the statistical variations of the mean and the systematics of the JES variations.
NOTE: for an explicit definition of the variables, see the additional docstring in the core of the code.
The second arguments of this function is the directory in which the histograms are written. This function creates the subdirectory structure necessary to store each series of variations corresponding to each $y_{probe}$ and $p_{T}^{ave}$ bins in a given directory. The structure of the output is:
file/ > dOut/ > eta1/ >
nominal (TH1, mean value of the $p_{T}^{bal}$ with statistical
unc.)
> upper (upper limit of the variations statistical+systematics)
> lower (lower limit of the variations staistical + systematics)
> ptbin1 > rec_any_vs_any_balance_0
> ...
> rec_any_vs_any_balance_${nVariations}
> ptbin2
> ...
> ptbin${nPtbins}
> ...
The structure at file/dOut/
level is identical to the structure of the input file.
We use the terminology used in AN2019_167_v13
:
- The balance A is : \(A = 2 \frac{p_{T,1}-p_{T,2}}{p_{T,1} + p_{T,2}} \)
- The mean balance is the quantity: \( R = \frac{1 - \fac{ \left\langle A \right\rangle }{2}}{1 + \frac{ \left\langle A \right\rangle }{2}}\)
73 const int N = variations.size();
74 Int_t nBins_local = variations.front()->GetNbinsY();
77 double LowEdges[nBins_local] = {0.};
78 variations.front()->GetYaxis()->GetLowEdge(LowEdges);
79 double genBins_local[nBins_local + 1];
80 for (
int i = 0 ; i<nBins_local ; ++i) genBins_local[i]=LowEdges[i];
81 genBins_local[nBins_local] = variations.front()->GetYaxis()->GetBinUpEdge(nBins_local);
84 for (
int y = 1 ; y <= variations.front()->GetNbinsZ() ; ++y) {
87 TDirectory *direta = dOut.mkdir( Form(
"eta%d", y) );
88 cout <<
"Creating directory " <<
bold << direta->GetPath() <<
normal << endl;
92 TH1 *
nominal =
new TH1F(
"nominal",
"", nBins_local, genBins_local),
93 *upper =
new TH1F(
"upper",
"", nBins_local, genBins_local),
94 *lower =
new TH1F(
"lower",
"", nBins_local, genBins_local);
98 upper->SetDirectory(direta);
99 lower->SetDirectory(direta);
102 nominal->SetXTitle(
"p_{T,ave}");
103 nominal->SetYTitle(
"#frac{1 - #LT #frac{#Delta p_{T}}{p_{T,ave}} #GT}{1 + #LT #frac{#Delta p_{T}}{p_{T,ave}} #GT }");
104 upper->SetXTitle(
"p_{T,ave}");
105 upper->SetYTitle(
"#frac{1 - #LT #frac{#Delta p_{T}}{p_{T,ave}} #GT}{1 + #LT #frac{#Delta p_{T}}{p_{T,ave}} #GT }");
106 lower->SetXTitle(
"p_{T,ave}");
107 lower->SetYTitle(
"#frac{1 - #LT #frac{#Delta p_{T}}{p_{T,ave}} #GT}{1 + #LT #frac{#Delta p_{T}}{p_{T,ave}} #GT }");
110 for (
int ipt = 1 ; ipt <= nBins_local ; ++ipt) {
114 double errUp = variations.front()->GetBinError(ipt),
115 errDn = errUp, content=0;
117 TDirectory *dirpt = direta->mkdir( Form(
"ptbin%d",ipt) );
119 cout <<
"Creating directory " <<
bold << dirpt->GetPath() <<
normal << endl;
122 for (
int sv=0 ; sv<N ; ++sv) {
123 auto balance = variations[sv]->ProjectionX(
"py", ipt, ipt, y, y,
"e");
124 balance->SetName(variations[sv]->GetName());
125 balance->SetTitle(variations[sv]->GetTitle());
126 balance->SetDirectory(dirpt);
127 double I = balance->Integral();
129 if (std::abs(I)<
deps) {
130 cout <<
"integral is null in bin (pt, eta): (" << ipt <<
"," << y <<
") in variation: " << sv << endl;
133 else balance->Scale(1./I);
135 double mean = balance->GetMean();
136 double meanErr = balance->GetMeanError();
144 double R = (1.-mean/2.)/(1.+mean/2.),
145 Rup = (1.-(mean+meanErr)/2.)/(1.+(mean+meanErr)/2.),
146 Rdn = (1.-(mean-meanErr)/2.)/(1.+(mean-meanErr)/2.);
149 nominal->SetBinContent(ipt, R);
150 nominal->SetBinError(ipt, std::abs(Rup-Rdn)/2.);
161 double& err = mean > content ? errUp : errDn;
162 err = hypot(err, mean - content);
168 upper->SetBinContent(ipt, (1.-(content+errUp)/2)/(1.+(content+errUp)/2) );
169 lower->SetBinContent(ipt, (1.-(content-errDn)/2)/(1.+(content-errDn)/2) );
◆ round_to()
double DAS::JetEnergy::round_to |
( |
double |
value, |
|
|
double |
precision = 1.0 |
|
) |
| |
|
inline |
Round number value to precision. Recover "lost" precision.
102 return round(value / precision) * precision;
◆ abseta_edges
const std::vector<double> abseta_edges = { 0.000, 0.261, 0.522, 0.783, 1.044, 1.305, 1.566, 1.740, 1.930, 2.043, 2.172, 2.322, 2.500, 2.650, 2.853, 2.964, 3.139, 3.489, 3.839, 5.191 } |
|
inlinestatic |
JERC binning (taken from JERCProtoLab repo, /macros/common_info/common_binning.hpp)
◆ absetaBins
const std::vector<TString> absetaBins = MakeTitle(abseta_edges, "|#eta|", false, true, [](double v) { return Form("%.3f", v);}) |
|
inlinestatic |
◆ deps
const auto deps = numeric_limits<double>::epsilon() |
|
static |
◆ eta_unc_edges
const std::vector<double> eta_unc_edges = {-5.4, -5.0, -4.4, -4.0, -3.5, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0 , 0.2 , 0.4 , 0.6 , 0.8 , 1.0 , 1.2 , 1.4 , 1.6 , 1.8 , 2.0 , 2.2 , 2.4 , 2.6 , 2.8 , 3.0, 3.5 , 4.0 , 4.4 , 5.0 , 5.4} |
|
inlinestatic |
binning for JES uncertainties (taken from JES files)
◆ JES_variations
const std::vector<std::string> JES_variations {"AbsoluteStat", "AbsoluteScale", "AbsoluteMPFBias", "Fragmentation", "SinglePionECAL", "SinglePionHCAL", "FlavorQCD", "RelativeJEREC1", "RelativeJEREC2", "RelativeJERHF", "RelativePtBB", "RelativePtEC1", "RelativePtEC2", "RelativePtHF", "RelativeBal", "RelativeSample", "RelativeFSR", "RelativeStatFSR", "RelativeStatEC", "RelativeStatHF", "PileUpDataMC", "PileUpPtRef", "PileUpPtBB", "PileUpPtEC1", "PileUpPtEC2", "PileUpPtHF"} |
|
inlinestatic |
◆ nAbsEtaBins
const int nAbsEtaBins = abseta_edges.size()-1 |
|
inlinestatic |
◆ nEtaUncBins
const int nEtaUncBins = eta_unc_edges.size()-1 |
|
inlinestatic |
◆ nPtJERCbins
const int nPtJERCbins = pt_JERC_edges.size()-1 |
|
inlinestatic |
◆ nRhoBins
const std::map<int,int> nRhoBins |
|
inlinestatic |
◆ pt_JERC_edges
const std::vector<double> pt_JERC_edges = {15, 17, 20, 23, 27, 30, 35, 40, 45, 57, 72, 90, 120, 150, 200, 300, 400, 550, 750, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500, 7000, 7500, 8000, 8500, 9000, 9500} |
|
inlinestatic |
◆ rho_edges
const std::map<int,std::vector<double> > rho_edges |
|
inlinestatic |
Initial value:= {
{ 2016, {0, 6.69, 12.39, 18.09, 23.79, 29.49, 35.19, 40.9, 999} },
{ 2017, {0, 7.47, 13.49, 19.52, 25.54, 31.57, 37.59, 999} },
{ 2018, {0, 7.35, 13.26, 19.17, 25.08, 30.99, 36.9, 999} }
}
◆ rhoBins
const std::map<int,std::vector<TString> > rhoBins |
|
inlinestatic |
Initial value:= {
{ 2016,
MakeTitle(
rho_edges.at(2016),
"#rho",
false,
false, [](
double v) { return Form(
"%.2f", v);}) },
{ 2017,
MakeTitle(
rho_edges.at(2017),
"#rho",
false,
false, [](
double v) { return Form(
"%.2f", v);}) },
{ 2018,
MakeTitle(
rho_edges.at(2018),
"#rho",
false,
false, [](
double v) { return Form(
"%.2f", v);}) }
}
- Todo:
- check exact list of variations with JME group
name
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:48
cerr
Definition: Ntupliser_cfg.py:93
bins
Definition: metPhiCorrectionExample.py:89
static const std::map< int, std::vector< double > > rho_edges
Definition: common.h:22
void loopDirsFromGetResponse(TDirectory *dIn, TDirectory *dOut, const int steering, const DT::Slice slice)
Definition: fitJetResponse.cc:456
pt
Definition: jmarExample.py:19
static bool verbose
Definition: Step.h:40
static const char * def
Definition: Step.h:36
FourVector p4
raw four-momentum directly after reconstruction
Definition: PhysicsObject.h:47
static const std::vector< double > eta_unc_edges
binning for JES uncertainties (taken from JES files)
Definition: common.h:42
static const char * underline
Definition: colours.h:10
vector< double > GetMergedBinning(TH1 *h, const int threshold=30)
Definition: fitJetResponse.cc:49
string algo
Definition: jercExample.py:60
void loopDirsFromGetBalance(TDirectory *dIn, TDirectory *dOut)
Definition: getPtAveBalance.cc:184
const std::string SysUp
Suffix used for "up" uncertainties. Follows the Combine convention.
Definition: Format.h:8
int year
Definition: Ntupliser_cfg.py:63
cset
Definition: jercExample.py:90
std::vector< TString > MakeTitle(const std::vector< double > &edges, const char *v, bool lowEdge, bool highEdge, std::function< const char *(double)> format)
Make a vector of properly formated titles from bin edges.
Definition: binnings.h:13
source
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:39
vector< TString > GetScaleVariations(const DT::MetaInfo &metainfo)
Definition: getPtBalance.cc:145
static const std::vector< double > pt_JERC_edges
Definition: common.h:13
p
Definition: Ntupliser_cfg.py:361
f
Definition: Ntupliser_cfg.py:255
TH1 * CumulativeResponse(TH1 *res1D)
Definition: fitJetResponse.cc:306
std::vector< float > scales
energy scale corrections and variations
Definition: PhysicsObject.h:48
string key
Definition: jercExample.py:109
void ProcessVariations(const vector< TH3 * > &variations, TDirectory &dOut)
Definition: getPtAveBalance.cc:71
void FitResponseByBin(TDirectory *dir, unique_ptr< TH2 > res2D, const int steering)
Definition: fitJetResponse.cc:328
unique_ptr< TH3 > makeRespHist(TString name, TString study)
Create TH3 histograms for the Jet response and HLT response.
Definition: MakeResponseHistos.h:20
bool pt_sort(const PhysicsObject &j1, const PhysicsObject &j2)
Definition: toolbox.h:18
static const double minpt
Definition: getMNobservables.cc:42
static const std::vector< std::string > JES_variations
Definition: common.h:45
genjets
Definition: Ntupliser_cfg.py:271
string jets
Definition: Ntupliser_cfg.py:41
DAS::RecJet recjet
Definition: classes.h:15
DAS::Weight weight
Definition: classes.h:11
static const char * red
Definition: Step.h:34
string unc
Definition: jercExample.py:70
config
Definition: Ntupliser_cfg.py:263
const Variation nominal
Definition: Variation.h:109
static const double maxpt
Definition: getMNobservables.cc:42
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:272
static const int nEtaUncBins
Definition: common.h:43
static const std::vector< double > abseta_edges
JERC binning (taken from JERCProtoLab repo, /macros/common_info/common_binning.hpp)
Definition: common.h:18
static const char * normal
Definition: colours.h:8
float CorrPt(size_t i=0) const
corrected transverse momentum
Definition: PhysicsObject.h:52
static const auto deps
Definition: getPtAveBalance.cc:38
const std::string SysDown
Suffix used for "down" uncertainties. Follows the Combine convention.
Definition: Format.h:10
string isMC
Definition: Ntupliser_cfg.py:59
std::string getAlgo(const Darwin::Tools::MetaInfo &metainfo)
Determine from metainfo if CHS or PUPPI has been used to reconstruct the jets.
Definition: common.h:86
static const std::map< int, int > nRhoBins
Definition: common.h:28
const float threshold
Definition: sigmoid.h:14
sf
Definition: jercExample.py:112
def inputs
Definition: jercExample.py:118
Generic exception for problematic event (during event loop).
Definition: exceptions.h:48
void loopDirsFromFitResponse(TDirectory *dIn, TDirectory *dOut, const int steering)
Definition: fitJetResolution.cc:193
static const int nPtJERCbins
Definition: common.h:14
void FitResolution(TDirectory *dir, unique_ptr< TH1 > h, const int steering)
Fit the resolution obtained from fitJetResponse in a given eta/rho bin.
Definition: fitJetResolution.cc:167
#define DT_GetOutput(output)
Definition: FileUtils.h:96
eta
DeepAK8/ParticleNet tagging.
Definition: jmarExample.py:19
static const int nYbins
Definition: binnings.h:38
static const int nAbsEtaBins
Definition: common.h:19
static const char * bold
Definition: Step.h:35