21namespace fs = std::filesystem;
29 m_showerGeneratorMapFile(
""),
30 m_showerGenerator(
""),
33 m_charmProdFractionWeights({}),
34 m_bottomProdFractionWeights({})
37 declareProperty(
"CalibrationAreaPath", m_calibrationAreaPath =
"xAODBTaggingEfficiency/13TeV/HFReweighting-2022-04-19_v1",
38 "Path to the calibration area");
41 declareProperty(
"ShowerGeneratorMapFile", m_showerGeneratorMapFile =
"HFProductionFractionsMap.txt",
42 "Input file name for the MC shower generator map");
45 declareProperty(
"ShowerGenerator", m_showerGenerator =
"",
46 "MC Shower generator software");
49 declareProperty(
"FiducialPtCut", m_fiducialPtCut = 5000,
50 "The fiducial charm/bottom pT cut. The recommended value is 5000 (MeV).");
53 declareProperty(
"FiducialEtaCut", m_fiducialEtaCut = 2.5,
54 "The fiducial charm/bottom eta cut. The recommended value is 2.5.");
65 return StatusCode::FAILURE;
84 return StatusCode::FAILURE;
91 ATH_MSG_WARNING(
"The property `ShowerGenerator' was set to 000000, which means that the tool will return dummy weights of 1.0");
95 return StatusCode::SUCCESS;
107 std::ifstream infile(filename);
109 int pdg1 = -1, pdg2 = -1, pdg3 = -1, pdg4 = -1;
110 while (std::getline(infile, line)) {
111 std::istringstream iss(line);
112 if (line.rfind(
"#", 0) == 0 || line.empty()) {
116 if (!(iss >> pdg1 >> pdg2 >> pdg3 >> pdg4)) {
118 return StatusCode::FAILURE;
122 float f1, f2, f3, f4;
123 if (!(iss >> sys >> f1 >> f2 >> f3 >> f4)) {
125 return StatusCode::FAILURE;
127 if (sys ==
"NOSYS") {
138 return StatusCode::SUCCESS;
147 if (mapFilename.empty()) {
149 return StatusCode::FAILURE;
154 std::ifstream infile(mapFilename);
156 while (std::getline(infile, line)) {
157 std::istringstream iss(line);
158 if (line.rfind(
"#", 0) == 0 || line.empty()) {
162 std::string id, name;
163 if (!(iss >>
id >> name)) {
165 return StatusCode::FAILURE;
168 }
else if (
id ==
"5") {
185 return StatusCode::FAILURE;
193 if (charmFilename.empty()) {
195 return StatusCode::FAILURE;
201 if (bottomFilename.empty()) {
203 return StatusCode::FAILURE;
216 if (filename.empty()) {
218 return StatusCode::FAILURE;
235 infile = std::ifstream(filename);
236 std::map<unsigned int, float> charm;
237 std::map<unsigned int, float> bottom;
238 while (std::getline(infile, line)) {
239 std::istringstream iss(line);
240 if (line.rfind(
"#", 0) == 0 || line.empty()) {
246 if (!(iss >> pdgId >> fraction)) {
248 return StatusCode::FAILURE;
250 if (pdgId == 4000 || pdgId < 500) {
251 ATH_MSG_DEBUG(
"Charm meson " << pdgId <<
" has a fraction of " << fraction);
252 charm[pdgId] = fraction;
254 ATH_MSG_DEBUG(
"Bottom meson " << pdgId <<
" has a fraction of " << fraction);
255 bottom[pdgId] = fraction;
267 for (
auto &kv : charm) {
274 for (
auto &kv : bottom) {
280 return StatusCode::SUCCESS;
284 for (
unsigned int i = 0; i < particle->nParents(); i++) {
285 if (particle->parent(i)->isHeavyHadron()) {
286 if (particle->parent(i)->isBottomHadron()) {
297 if (tp->nParents() < 1) {
302 for (
unsigned int i = 0; i < tp->nParents(); i++) {
303 if (tp->parent(i) && (tp->parent(i)->absPdgId() == tp->absPdgId())) {
305 if (initialParticle && out && (initialParticle != out)) {
307 throw std::runtime_error(
"Contradictory information in the truth decay chain!");
309 out = initialParticle;
321 std::set<const xAOD::TruthParticle *> bottomHadrons;
322 std::set<const xAOD::TruthParticle *> charmHadrons;
329 if (tp->isBottomHadron())
335 if (tp->isCharmHadron()) {
346 for (
auto *tp : charmHadrons) {
347 int pdgId = tp->absPdgId();
351 }
else if (pdgId == 4122 ||
357 ATH_MSG_DEBUG(
"Charm weight for pdgId " << pdgId <<
", pT " << tp->pt() <<
", eta " << tp->eta() <<
": " << w);
362 for (
auto *tp : bottomHadrons) {
363 int pdgId = tp->absPdgId();
367 }
else if (pdgId == 5122 ||
373 ATH_MSG_DEBUG(
"Bottom weight for pdgId " << pdgId <<
", pT " << tp->pt() <<
", eta " << tp->eta() <<
": " << w);
383 return getWeight(truthParticles, *prod_fracs);
391 ATH_MSG_INFO(
"Currently set weights for charm production fractions:");
394 for (
auto const &kv : generator.second) {
400 ATH_MSG_INFO(
"Currently set weights for bottom production fractions:");
403 for (
auto const &kv : generator.second) {
410 if (systConfig.
size() > 1) {
411 ATH_MSG_ERROR(
"Multiple systematic variations in one SystematicsSet are not supported");
412 return StatusCode::FAILURE;
418 return StatusCode::FAILURE;
423 return StatusCode::FAILURE;
430 if (systConfig.
size() == 1) {
445 return StatusCode::SUCCESS;
451 ATH_MSG_WARNING(
"The property `ShowerGenerator' was set to 000000. The tool will now return an empty SystematicsSet and dummy weights of 1.0");
455 ATH_MSG_ERROR(
"The production fraction weights were not properly initialized!");
456 throw std::runtime_error(
"Charm or bottom production fraction weight map is empty!");
460 if(!kv.first.empty())
464 if(!kv.first.empty())
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
This module implements the central registry for handling systematic uncertainties with CP tools.
static SystematicRegistry & getInstance()
Get the singleton instance of the registry for the curren thread.
StatusCode registerSystematics(const IReentrantSystematicsTool &tool)
effects: register all the systematics from the tool
Class to wrap a set of SystematicVariations.
const_iterator begin() const
description: const iterator to the beginning of the set
size_t size() const
returns: size of the set
TruthParticle_v1 TruthParticle
Typedef to implementation.
TruthParticleContainer_v1 TruthParticleContainer
Declare the latest version of the truth particle container.