103 std::map<int, std::string> debugStr = {
113 decayDescriptor.init(decayString);
114 auto pListName = decayDescriptor.getMother()->getFullName();
116 unsigned short m_nSelectedDaughters = decayDescriptor.getSelectionNames().size();
120 B2FATAL(
"ParticleList: " << pListName <<
" could not be found. Aborting...");
123 auto pListSize = pList->getListSize();
125 B2DEBUG(11,
"ParticleList: " << pList->getParticleListName() <<
" - N = " << pListSize <<
" particles.");
127 const auto nTargetParticles = (m_nSelectedDaughters == 0) ? pListSize : pListSize * m_nSelectedDaughters;
130 std::vector<int> pdgs;
131 if (m_nSelectedDaughters == 0) {
132 pdgs.push_back(pList->getPDGCode());
134 pdgs = decayDescriptor.getSelectionPDGCodes();
136 for (
auto pdg : pdgs) {
139 B2FATAL(
"PDG: " << pdg <<
" of ParticleList: " << pListName <<
140 " is not that of a valid particle in Const::chargedStableSet! Aborting...");
143 std::vector<const Particle*> targetParticles;
144 if (m_nSelectedDaughters > 0) {
145 for (
unsigned int iPart(0); iPart < pListSize; ++iPart) {
146 auto* iParticle = pList->getParticle(iPart);
147 auto daughters = decayDescriptor.getSelectionParticles(iParticle);
148 for (
auto* iDaughter : daughters) {
149 targetParticles.push_back(iDaughter);
154 for (
unsigned int ipart(0); ipart < nTargetParticles; ++ipart) {
156 const Particle* particle = (m_nSelectedDaughters == 0) ? pList->getParticle(ipart) : targetParticles[ipart];
160 const ECLCluster* eclCluster = particle->getECLCluster();
162 B2DEBUG(11,
"\nParticle [" << ipart <<
"] has invalid Track-ECLCluster relation, skip MVA application...");
171 auto p = particle->getP();
174 if (std::isnan(theta) or std::isnan(p) or std::isnan(charge)) {
175 B2DEBUG(11,
"\nParticle [" << ipart <<
"] has invalid input variable, skip MVA application..." <<
176 " polar angle: " << theta <<
", p: " << p <<
", charge: " << charge);
180 int idx_theta, idx_p, idx_charge;
183 auto hasMatch = std::isnormal(Variable::eclClusterTrackMatched(particle));
185 debugStr[11] +=
"\n";
186 debugStr[11] += (
"Particle [" + std::to_string(ipart) +
"]\n");
187 debugStr[11] += (
"Has ECL cluster match? " + std::to_string(hasMatch) +
"\n");
188 debugStr[11] += (
"polar angle: " + thVarName +
" = " + std::to_string(theta) +
" [rad]\n");
189 debugStr[11] += (
"p = " + std::to_string(p) +
" [GeV/c]\n");
191 debugStr[11] += (
"charge = " + std::to_string(charge) +
"\n");
193 debugStr[11] += (
"Is brems corrected ? " + std::to_string(particle->hasExtraInfo(
"bremsCorrected")) +
"\n");
194 debugStr[11] += (
"Weightfile idx = " + std::to_string(index) +
" - (polar angle, p, charge) = (" + std::to_string(
195 idx_theta) +
", " + std::to_string(idx_p) +
", " +
196 std::to_string(idx_charge) +
")\n");
198 debugStr[11] += (
"Category cut: " +
m_cuts.at(index)->decompile() +
"\n");
201 B2DEBUG(11, debugStr[11]);
202 debugStr[11].clear();
206 if (!
m_cuts.at(index)->check(particle)) {
207 B2DEBUG(11,
"\nParticle [" << ipart <<
"] didn't pass MVA category cut, skip MVA application...");
214 debugStr[11] +=
"\n";
215 debugStr[11] +=
"MVA variables:\n";
218 for (
unsigned int ivar(0); ivar < nvars; ++ivar) {
222 double var = std::numeric_limits<double>::quiet_NaN();
223 auto var_result = varobj->function(particle);
224 if (std::holds_alternative<double>(var_result)) {
225 var = std::get<double>(var_result);
226 }
else if (std::holds_alternative<int>(var_result)) {
227 var = std::get<int>(var_result);
228 }
else if (std::holds_alternative<bool>(var_result)) {
229 var = std::get<bool>(var_result);
231 B2ERROR(
"Variable '" << varobj->name <<
"' has wrong data type! It must be one of double, integer, or bool.");
236 var = (std::isnan(var)) ? -999.0 : var;
239 debugStr[11] += (
"\tvar[" + std::to_string(ivar) +
"] : " + varobj->name +
" = " + std::to_string(var) +
"\n");
245 B2DEBUG(11, debugStr[11]);
246 debugStr[11].clear();
251 debugStr[12] +=
"\n";
252 debugStr[12] +=
"MVA spectators:\n";
255 for (
unsigned int ispec(0); ispec < nspecs; ++ispec) {
259 double spec = std::numeric_limits<double>::quiet_NaN();
260 auto spec_result = specobj->function(particle);
261 if (std::holds_alternative<double>(spec_result)) {
262 spec = std::get<double>(spec_result);
263 }
else if (std::holds_alternative<int>(spec_result)) {
264 spec = std::get<int>(spec_result);
265 }
else if (std::holds_alternative<bool>(spec_result)) {
266 spec = std::get<bool>(spec_result);
268 B2ERROR(
"Variable '" << specobj->name <<
"' has wrong data type! It must be one of double, integer, or bool.");
271 debugStr[12] += (
"\tspec[" + std::to_string(ispec) +
"] : " + specobj->name +
" = " + std::to_string(spec) +
"\n");
273 m_datasets.at(index)->m_spectators[ispec] = spec;
277 B2DEBUG(12, debugStr[12]);
278 debugStr[12].clear();
284 debugStr[11] +=
"\n";
285 debugStr[12] +=
"\n";
286 debugStr[11] +=
"MVA response:\n";
290 debugStr[11] += (
"\tscore = " + std::to_string(score));
296 B2DEBUG(11, debugStr[11]);
297 B2DEBUG(12, debugStr[12]);
298 debugStr[11].clear();
299 debugStr[12].clear();
314 std::map<std::string, std::string> aliasesLegacy;
316 aliasesLegacy.insert(std::make_pair(
"__event__",
"evtNum"));
323 aliasesLegacy.insert(std::make_pair(
"missingLogL_" + detName,
"pidMissingProbabilityExpert(" + detName +
")"));
327 std::string alias =
"deltaLogL_" + std::get<0>(info) +
"_" + std::get<1>(info) +
"_" + detName;
328 std::string var =
"pidDeltaLogLikelihoodValueExpert(" + std::to_string(pdgId) +
", " + std::to_string(std::get<2>
329 (info)) +
"," + detName +
")";
331 aliasesLegacy.insert(std::make_pair(alias, var));
333 if (it.getIndex() == 0) {
334 alias =
"deltaLogL_" + std::get<0>(info) +
"_" + std::get<1>(info) +
"_ALL";
335 var =
"pidDeltaLogLikelihoodValueExpert(" + std::to_string(pdgId) +
", " + std::to_string(std::get<2>(info)) +
", ALL)";
336 aliasesLegacy.insert(std::make_pair(alias, var));
343 B2INFO(
"Setting hard-coded aliases for the ChargedPidMVA algorithm.");
345 std::string debugStr(
"\n");
346 for (
const auto& [alias, variable] : aliasesLegacy) {
347 debugStr += (alias +
" --> " + variable +
"\n");
349 B2ERROR(
"Something went wrong with setting alias: " << alias <<
" for variable: " << variable);
352 B2DEBUG(10, debugStr);
390 B2INFO(
"Run: " <<
m_event_metadata->getRun() <<
". Load supported MVA interfaces for binary charged particle identification...");
399 B2INFO(
"\tLoading weightfiles from the payload class for SIGNAL particle hypothesis: " <<
m_sig_pdg);
402 auto nfiles = serialized_weightfiles->size();
404 B2INFO(
"\tConstruct the MVA experts and datasets from N = " << nfiles <<
" weightfiles...");
414 for (
unsigned int idx(0); idx < nfiles; idx++) {
416 B2DEBUG(12,
"\t\tweightfile[" << idx <<
"]");
419 std::stringstream ss(serialized_weightfiles->at(idx));
423 weightfile.getOptions(general_options);
427 m_variables[idx] = manager.getVariables(general_options.m_variables);
428 m_spectators[idx] = manager.getVariables(general_options.m_spectators);
430 B2DEBUG(12,
"\t\tRetrieved N = " << general_options.m_variables.size()
431 <<
" variables, N = " << general_options.m_spectators.size()
435 m_experts[idx] = supported_interfaces[general_options.m_method]->getExpert();
438 B2DEBUG(12,
"\t\tweightfile loaded successfully into expert[" << idx <<
"]!");
441 std::vector<float> v(general_options.m_variables.size(), 0.0);
442 std::vector<float> s(general_options.m_spectators.size(), 0.0);
443 m_datasets[idx] = std::make_unique<MVA::SingleDataset>(general_options, v, 1.0, s);
445 B2DEBUG(12,
"\t\tdataset[" << idx <<
"] created successfully!");
449 const auto cutstr = (!cuts->empty()) ? cuts->at(idx) :
"";
452 B2DEBUG(12,
"\t\tcut[" << idx <<
"] created successfully!");
Class to store reconstructed particles.