10#include <analysis/variables/FEIVariables.h>
13#include <analysis/VariableManager/Manager.h>
15#include <analysis/dataobjects/Particle.h>
16#include <analysis/dataobjects/ParticleList.h>
17#include <analysis/utility/PCmsLabTransform.h>
18#include <framework/gearbox/Const.h>
19#include <mdst/dataobjects/MCParticle.h>
20#include <framework/datastore/StoreArray.h>
21#include <framework/datastore/StoreObjPtr.h>
33 int mostcommonBTagIndex(
const Particle* part)
35 std::map <int, int> tag_candidates;
36 const std::vector<const Particle*>& fsp_tag = part->getFinalStateDaughters();
37 for (
const Particle* fsp : fsp_tag) {
38 const MCParticle* mc_fsp = fsp->getMCParticle();
40 int tag_index = finddescendant(mc_fsp);
41 if (tag_candidates.find(tag_index) == tag_candidates.end()) {
42 tag_candidates[tag_index] = 1;
44 tag_candidates[tag_index]++;
50 for (
const auto& [key, value] : tag_candidates) {
58 int finddescendant(
const MCParticle* mcpart)
60 const MCParticle* i_mcpart = mcpart;
62 const auto* i_mcpart_mother = i_mcpart->getMother();
63 if (i_mcpart_mother) {
64 constexpr std::array<int, 2> B_PDG = {511, 521};
65 auto result = std::find(B_PDG.begin(), B_PDG.end(), abs(i_mcpart_mother->getPDG()));
66 if (result != B_PDG.end()) {
67 return i_mcpart_mother->getArrayIndex();
69 i_mcpart = i_mcpart_mother;
76 std::vector<int> truthFSPTag(
int BTag_index)
78 StoreArray<MCParticle> MC_Particle_list;
79 std::vector<int> fsp_truth_index;
80 for (
const MCParticle& iMCParticle : MC_Particle_list) {
84 fsp_truth_index.push_back(iMCParticle.getArrayIndex());
87 return fsp_truth_index;
89 double percentageMissingParticlesBTag(
const Particle* part)
91 int index = mostcommonBTagIndex(part);
95 std::vector<int> fsp_FEI_index;
96 const std::vector<const Particle*>& fsp_tag = part->getFinalStateDaughters();
97 for (
const Particle* fsp : fsp_tag) {
98 const MCParticle* mc_fsp = fsp->getMCParticle();
100 int tag_index = finddescendant(mc_fsp);
101 if (tag_index == index) {
102 fsp_FEI_index.push_back(mc_fsp->getArrayIndex());
106 std::vector<int> diff;
107 std::vector<int> fsp_truth_index = truthFSPTag(index);
108 std::sort(fsp_truth_index.begin(), fsp_truth_index.end());
109 std::sort(fsp_FEI_index.begin(), fsp_FEI_index.end());
110 std::set_difference(fsp_truth_index.begin(), fsp_truth_index.end(), fsp_FEI_index.begin(), fsp_FEI_index.end(), std::inserter(diff,
112 return double(diff.size()) / double(fsp_truth_index.size());
115 double percentageWrongParticlesBTag(
const Particle* part)
117 int index = mostcommonBTagIndex(part);
121 const std::vector<const Particle*>& fsp_tag = part->getFinalStateDaughters();
123 for (
const Particle* fsp : fsp_tag) {
124 const MCParticle* mc_fsp = fsp->getMCParticle();
126 int tag_index = finddescendant(mc_fsp);
127 if (tag_index != index) {
132 return double(wrong_FEI) / double(truthFSPTag(index).size());
135 double mostcommonBTagDeltaP(
const Particle* part)
137 int idx = mostcommonBTagIndex(part);
140 StoreArray<MCParticle> mcParticles;
142 ROOT::Math::XYZVector recoP3 = (T.rotateLabToCms() * part->get4Vector()).Vect();
143 ROOT::Math::XYZVector genP3 = (T.rotateLabToCms() * mcParticles[idx]->get4Vector()).Vect();
144 return (recoP3 - genP3).R();
147 double mostcommonBTagPDG(
const Particle* part)
149 int idx = mostcommonBTagIndex(part);
152 StoreArray<MCParticle> mcParticles;
153 return mcParticles[idx]->getPDG();
158 if (arguments.size() != 2) {
159 B2FATAL(
"sigProbRank requires exactly 2 arguments: bp_list and b0_list. "
160 "Received " << arguments.size() <<
" arguments.");
163 std::string bpListName = arguments[0];
164 std::string b0ListName = arguments[1];
166 auto func = [bpListName, b0ListName](
const Particle * particle) ->
int {
167 StoreObjPtr<ParticleList> bpList(bpListName);
168 StoreObjPtr<ParticleList> b0List(b0ListName);
170 if (!bpList.isValid() && !b0List.isValid())
171 B2FATAL(
"sigProbRank could not find either input list: bp_list='" << bpListName
172 <<
"', b0_list='" << b0ListName <<
"'");
173 if (!bpList.isValid())
174 B2FATAL(
"sigProbRank could not find the required bp_list: '" << bpListName <<
"'");
175 if (!b0List.isValid())
176 B2FATAL(
"sigProbRank could not find the required b0_list: '" << b0ListName <<
"'");
178 struct RankedCandidate {
179 double signalProbability;
180 const Particle* particle;
183 auto collectCandidates = [](
const StoreObjPtr<ParticleList>& list,
184 const std::string & listLabel,
185 std::vector<RankedCandidate>& rankedCandidates)
187 for (
unsigned int i = 0; i < list->getListSize(); ++i) {
188 const Particle* p = list->getParticle(i);
189 if (!p->hasExtraInfo(
"SignalProbability")) {
190 B2FATAL(
"sigProbRank requires every candidate in " << listLabel
191 <<
" to provide extraInfo('SignalProbability')");
193 rankedCandidates.push_back({p->getExtraInfo(
"SignalProbability"), p});
197 std::vector<RankedCandidate> rankedCandidates;
198 rankedCandidates.reserve(bpList->getListSize() + b0List->getListSize());
199 collectCandidates(bpList, bpListName, rankedCandidates);
200 collectCandidates(b0List, b0ListName, rankedCandidates);
202 std::stable_sort(rankedCandidates.begin(), rankedCandidates.end(),
203 [](
const RankedCandidate & lhs,
const RankedCandidate & rhs)
205 return lhs.signalProbability > rhs.signalProbability;
211 int originalIndex = -1;
212 if (particle->hasExtraInfo(
"original_index"))
213 originalIndex =
static_cast<int>(particle->getExtraInfo(
"original_index"));
215 for (
unsigned int i = 0; i < rankedCandidates.size(); ++i)
217 const Particle* cand = rankedCandidates[i].particle;
218 if (cand == particle) {
219 return static_cast<int>(i) + 1;
221 if (originalIndex >= 0 && cand->getArrayIndex() == originalIndex) {
222 return static_cast<int>(i) + 1;
226 B2FATAL(
"sigProbRank: particle not found in the input lists: "
227 "bp_list='" << bpListName <<
"', b0_list='" << b0ListName <<
"'");
233 VARIABLE_GROUP(
"FEIVariables");
234 REGISTER_VARIABLE(
"mostcommonBTagIndex", mostcommonBTagIndex,
235 "By giving e.g. a FEI B meson candidate the B meson index on generator level is determined, where most reconstructed particles can be assigned to. If no B meson found on generator level -1 is returned.");
236 REGISTER_VARIABLE(
"percentageMissingParticlesBTag", percentageMissingParticlesBTag,
237 "Get the percentage of missing particles by using the mostcommonBTagIndex. So the number of particles not reconstructed by e.g. the FEI are determined and divided by the number of generated particles using the given index of the B meson. If no B meson found on generator level -1 is returned.");
238 REGISTER_VARIABLE(
"percentageWrongParticlesBTag", percentageWrongParticlesBTag,
239 "Get the percentage of wrong particles by using the mostcommonBTagIndex. In this context wrong means that the reconstructed particles originated from the other B meson. The absolute number is divided by the total number of generated FSP from the given B meson index. If no B meson found on generator level -1 is returned.");
240 REGISTER_VARIABLE(
"mostcommonBTagDeltaP", mostcommonBTagDeltaP,
241 "Returns the magnitude of the 3-momentum difference in CMS frame between the "
242 "reconstructed particle and the generated B meson identified by mostcommonBTagIndex. "
243 "Returns NaN if no B meson is found on generator level.",
"GeV/c");
244 REGISTER_VARIABLE(
"mostcommonBTagPDG", mostcommonBTagPDG,
245 "Returns the PDG code of the generated B meson identified by mostcommonBTagIndex. "
246 "Returns NaN if no B meson is found on generator level. "
247 "Note: this is equivalent to ``genParticle(mostcommonBTagIndex, PDG)``. "
248 "Other variables can be accessed the same way by replacing ``PDG`` with any variable.");
249 REGISTER_METAVARIABLE(
"sigProbRank(bp_list, b0_list)", sigProbRank,
250 "Returns the rank (starting at 1) of the candidate when all candidates from the B+ list (bp_list) "
251 "and B0 list (b0_list) are ordered together by descending ``extraInfo(SignalProbability)``.", Manager::VariableDataType::c_int);
static const double doubleNaN
quiet_NaN
@ c_IsFSRPhoton
bit 7: Particle is from final state radiation
@ c_IsPHOTOSPhoton
bit 8: Particle is an radiative photon from PHOTOS
@ c_StableInGenerator
bit 1: Particle is stable, i.e., not decaying in the generator.
@ c_IsISRPhoton
bit 6: Particle is from initial state radiation
std::function< VarVariant(const Particle *)> FunctionPtr
functions stored take a const Particle* and return VarVariant.
Abstract base class for different kinds of events.