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];
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.
const ECLCluster * getECLCluster() const
Returns the pointer to the ECLCluster object that was used to create this Particle (if ParticleType =...
bool hasExtraInfo(const std::string &name) const
Return whether the extra info with the given name is set.
double getCharge(void) const
Returns particle charge.
double getP() const
Returns momentum magnitude (same as getMomentumMagnitude but with shorter name)