9 #include <analysis/modules/BestCandidateSelection/BestCandidateSelectionModule.h>
11 #include <analysis/utility/ValueIndexPairSorting.h>
13 #include <analysis/VariableManager/Utility.h>
15 #include <framework/logging/Logger.h>
16 #include <framework/utilities/MakeROOTCompatible.h>
29 setDescription(R
"DOC(Sort particles by the value of a given ``variable``
30 in the input list and optionally remove particles after the nth position.
32 Per default particles are sorted in descending order but it can be switched to
33 an ascending order by setting ``selectLowest=True``. The convenience functions
34 `modularAnalysis.rankByHighest` and `modularAnalysis.rankByLowest` set this
35 parameter automatically based on their names.
37 Particles will receive an extra-info field containing their rank as an integer
38 starting at 1 (best). The name of this extra-info field defaults to
39 ``${variable}_rank`` but can be chosen freely using the ``outputVariable``
42 The ranking also takes antiparticles into account, so there will only be one
43 B+- candidate with ``rank=1``. The remaining list is sorted from best to worst
44 candidate (each charge, e.g. B+/B-, separately). The sorting is guaranteed
45 to be stable between particle and anti particle list: particles with the same
46 value for ``variable`` will keep their relative order. That is, a particle "A"
47 which was before another particle "B" in the same list and has the same value
48 for ``variable`` will also stay before "B" after sorting.
50 If ``allowMultiRank=False`` (the default) candidates with same value of
51 ``variable`` will have different ranks. If ``allowMultiRank=True`` they will
54 IF ``numBest>0`` only candidates with this rank or better will remain in the
55 output list. If ``allowMultiRank=True`` that means that there can be more than
56 ``numBest`` candidates in the output list if they share ranks.
59 setPropertyFlags(c_ParallelProcessingCertified);
61 addParam("particleList", m_inputListName,
"Name of the ParticleList to rank for best candidate");
62 addParam(
"variable", m_variableName,
"Variable which defines the candidate ranking (see ``selectLowest`` for ordering)");
63 addParam(
"selectLowest", m_selectLowest,
"If true, candidate with lower values of ``variable`` are better, otherwise higher is better",
false);
64 addParam(
"allowMultiRank", m_allowMultiRank,
"If true, candidates with identical values get identical rank",
false);
65 addParam(
"numBest", m_numBest,
"Keep only particles with this rank or better. If ``allowMultiRank=False`` this is "
66 "identical to the maximum amount of candidates left in the list. Otherwise there may be more candidates if "
67 "some share the same rank (0: keep all)", 0);
68 addParam(
"cut", m_cutParameter,
"Only candidates passing the cut will be ranked. The others will have rank -1.", std::string(
""));
69 addParam(
"outputVariable", m_outputVariableName,
70 "Name for created variable, which contains the rank for the particle. If not provided, the standard name ``${variable}_rank`` is used.");
74 BestCandidateSelectionModule::~BestCandidateSelectionModule() =
default;
76 void BestCandidateSelectionModule::initialize()
78 m_particles.isRequired();
79 m_inputList.isRequired(m_inputListName);
81 m_variable = Variable::Manager::Instance().getVariable(m_variableName);
83 B2ERROR(
"Variable '" << m_variableName <<
"' is not available in Variable::Manager!");
86 B2ERROR(
"value of numBest must be >= 0!");
88 m_cut = Variable::Cut::compile(m_cutParameter);
91 if (m_outputVariableName.empty()) {
93 m_outputVariableName = root_compatible_VariableName +
"_rank";
97 void BestCandidateSelectionModule::event()
101 B2WARNING(
"Input list " << m_inputList.getName() <<
" was not created?");
106 typedef std::pair<double, unsigned int> ValueIndexPair;
107 std::vector<ValueIndexPair> valueToIndex;
108 const unsigned int numParticles = m_inputList->getListSize();
109 valueToIndex.reserve(numParticles);
110 for (
const Particle& p : *m_inputList) {
111 double value = m_variable->function(&p);
112 valueToIndex.emplace_back(value, p.getArrayIndex());
117 if (m_selectLowest) {
118 std::stable_sort(valueToIndex.begin(), valueToIndex.end(), ValueIndexPairSorting::lowerPair<ValueIndexPair>);
120 std::stable_sort(valueToIndex.begin(), valueToIndex.end(), ValueIndexPairSorting::higherPair<ValueIndexPair>);
124 m_inputList->clear();
126 double previous_val{0};
127 bool first_candidate{
true};
128 for (
const auto& candidate : valueToIndex) {
129 Particle* p = m_particles[candidate.second];
130 if (!m_cut->check(p)) {
131 p->addExtraInfo(m_outputVariableName, -1);
132 m_inputList->addParticle(p);
135 if (first_candidate) {
136 first_candidate =
false;
138 if (!m_allowMultiRank || (candidate.first != previous_val)) ++rank;
141 if (!p->hasExtraInfo(m_outputVariableName))
142 p->addExtraInfo(m_outputVariableName, rank);
143 m_inputList->addParticle(p);
145 previous_val = candidate.first;
147 if (m_numBest != 0 and rank >= m_numBest)
Ranks particles by the values of a variable.
Class to store reconstructed particles.
std::string makeROOTCompatible(std::string str)
Remove special characters that ROOT dislikes in branch names, e.g.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.