9 #include <analysis/modules/TrackIsoCalculator/TrackIsoCalculatorModule.h>
10 #include <analysis/DecayDescriptor/DecayDescriptorParticle.h>
14 #include <boost/algorithm/string.hpp>
25 R
"DOC(Calculate track isolation variables on the charged stable particles, or selected charged daughters, of the input ParticleList.)DOC");
30 "The name of the input charged stable particle list, e.g. ``mu+:all``, or a composite particle w/ charged stable daughters for which distances are to be calculated, e.g. ``D0 -> ^K- pi+``. Note that in the latter case we allow only one daughter to be selected in the decay string per module instance.");
33 "The name of the input ParticleList of reference tracks. Must be a charged stable particle as defined in Const::chargedStableSet.");
36 "The name of the detector at whose (cylindrical) surface(s) we extrapolate each helix's polar and azimuthal angle. Allowed values: {CDC, TOP, ARICH, ECL, KLM}.");
39 "If this option is set, the helix extrapolation for the target and reference particles will use the track fit result for the most probable mass hypothesis, namely, the one that gives the highest chi2Prob of the fit.",
43 "The name of the database payload object with the PID detector weights.",
44 std::string(
"PIDDetectorWeights"));
47 "If set to true, will not use the PID detector weights for the score definition.",
74 B2ERROR(
"More than one daughter is selected in the decay string " <<
m_decayString <<
".");
79 B2INFO(
"Calculating track-based isolation variables at "
81 <<
" surface(s) for the decay string: "
83 <<
" using the reference ParticleList: "
88 B2ERROR(
"Selected ParticleList in decay string:"
90 <<
" and/or reference ParticleList: "
92 <<
" is not that of a valid particle in Const::chargedStableSet!");
96 B2INFO(
"Will use track fit result for the most probable mass hypothesis in helix extrapolation.");
108 auto iDetLayer =
m_detName + std::to_string(iLayer);
112 distVarName +=
"__useHighestProbMassForExt";
138 std::unordered_map<unsigned int, const Particle*> targetParticles;
139 targetParticles.reserve(nMotherParticles);
144 auto iDetLayer =
m_detName + std::to_string(iLayer);
146 for (
unsigned int iPart(0); iPart < nMotherParticles; ++iPart) {
157 targetParticles.insert({iDaughter->getMdstArrayIndex(), iDaughter});
163 targetParticles.insert({iParticle->getMdstArrayIndex(), iParticle});
169 const auto nParticlesTarget = targetParticles.size();
175 auto iDetLayer =
m_detName + std::to_string(iLayer);
178 <<
"Detector surface: " << iDetLayer <<
"\n"
179 <<
"nMotherParticles: " << nMotherParticles <<
"\n"
180 <<
"nParticlesTarget: " << nParticlesTarget <<
"\n"
181 <<
"nParticlesReference: " << nParticlesReference);
183 double dummyDist(-1.0);
187 std::map<std::pair<unsigned int, unsigned int>,
double> particleMdstIdxPairsToDist;
190 for (
const auto& targetParticle : targetParticles) {
192 auto iMdstIdx = targetParticle.first;
193 auto iParticle = targetParticle.second;
195 for (
unsigned int jPart(0); jPart < nParticlesReference; ++jPart) {
198 auto jMdstIdx = jParticle->getMdstArrayIndex();
200 auto partMdstIdxPair = std::make_pair(iMdstIdx, jMdstIdx);
203 if (iMdstIdx == jMdstIdx) {
204 particleMdstIdxPairsToDist[partMdstIdxPair] = dummyDist;
214 if (particleMdstIdxPairsToDist.count({jMdstIdx, iMdstIdx})) {
215 particleMdstIdxPairsToDist[partMdstIdxPair] = particleMdstIdxPairsToDist[ {jMdstIdx, iMdstIdx}];
220 particleMdstIdxPairsToDist[partMdstIdxPair] = this->
getDistAtDetSurface(iParticle, jParticle, iDetLayer);
226 for (
const auto& targetParticle : targetParticles) {
228 auto iMdstIdx = targetParticle.first;
229 auto iParticle = targetParticle.second;
232 std::vector<std::pair<double, unsigned int>> iDistancesAndRefMdstIdxs;
233 for (
const auto& [mdstIdxs, dist] : particleMdstIdxPairsToDist) {
234 if (mdstIdxs.first == iMdstIdx) {
235 if (!std::isnan(dist) && dist >= 0) {
236 iDistancesAndRefMdstIdxs.push_back(std::make_pair(dist, mdstIdxs.second));
241 if (!iDistancesAndRefMdstIdxs.size()) {
242 B2DEBUG(12,
"The container of distances is empty. Perhaps the target and reference lists contain the same exact particles?");
246 const auto minDist = *std::min_element(std::begin(iDistancesAndRefMdstIdxs), std::end(iDistancesAndRefMdstIdxs),
247 [](
const auto & l,
const auto & r) {
return l.first < r.first;});
252 <<
"Particle w/ mdstIndex[" << iMdstIdx <<
"] (PDG = "
253 << iParticle->getPDGCode() <<
"). Closest charged particle w/ mdstIndex["
255 <<
"] (PDG = " << jParticle->getPDGCode()
256 <<
") at " << iDetLayer
257 <<
" surface is found at D = " << minDist.first
259 <<
"Storing extraInfo variables:\n"
274 for (
const auto& targetParticle : targetParticles) {
276 auto iMdstIdx = targetParticle.first;
277 auto iParticle = targetParticle.second;
283 <<
"Particle w/ mdstIndex[" << iMdstIdx <<
"] (PDG = " << iParticle->getPDGCode() <<
").\n"
284 <<
"Isolation score in the " <<
m_detName <<
": s = " << score
286 <<
"Storing extraInfo variable:\n"
301 auto p = iParticle->
getP();
304 double detWeight(-1.0);
306 detWeight = (*
m_DBWeights.get())->getWeight(hypo, det, p, theta);
310 detWeight = (detWeight < 0 || std::isnan(detWeight)) ? detWeight : 0.0;
315 auto iDetLayer =
m_detName + std::to_string(iLayer);
326 B2DEBUG(12,
"\nNo close-enough neighbours to this particle in the " <<
m_detName <<
" were found.");
332 <<
"Layers w/ a close-enough particle: n=" << n
334 <<
"n > N ?? Abort...");
337 return 1. - (-detWeight * (n /
m_nLayers));
344 const std::string& detLayerName)
const
357 std::string nameExtTheta =
"helixExtTheta(" + std::to_string(rho) +
"," + std::to_string(zfwd) +
"," + std::to_string(zbwd) +
")";
359 nameExtTheta.replace(nameExtTheta.size() - 1, 1,
", 1)");
364 std::string nameExtPhi =
"helixExtPhi(" + std::to_string(rho) +
"," + std::to_string(zfwd) +
"," + std::to_string(zbwd) +
")";
366 nameExtPhi.replace(nameExtPhi.size() - 1, 1,
", 1)");
371 const auto iExtInBarrel = (iExtTheta >= th_fwd_brl && iExtTheta < th_bwd_brl);
372 const auto jExtInBarrel = (jExtTheta >= th_fwd_brl && jExtTheta < th_bwd_brl);
374 const auto iExtInFWDEndcap = (iExtTheta >= th_fwd && iExtTheta < th_fwd_brl);
375 const auto jExtInFWDEndcap = (jExtTheta >= th_fwd && jExtTheta < th_fwd_brl);
377 const auto iExtInBWDEndcap = (iExtTheta >= th_bwd_brl && iExtTheta < th_bwd);
378 const auto jExtInBWDEndcap = (jExtTheta >= th_bwd_brl && jExtTheta < th_bwd);
383 if (!iExtInBarrel || !jExtInBarrel) {
384 return std::numeric_limits<double>::quiet_NaN();
391 auto diffPhi = jExtPhi - iExtPhi;
392 if (std::abs(diffPhi) > M_PI) {
393 diffPhi = (diffPhi > M_PI) ? diffPhi - 2 * M_PI : 2 * M_PI + diffPhi;
396 return 2.0 * rho * sin(std::abs(diffPhi) / 2.0);
402 if (!iExtInFWDEndcap || !jExtInFWDEndcap) {
403 return std::numeric_limits<double>::quiet_NaN();
411 !(iExtInBarrel && jExtInBarrel) &&
412 !(iExtInFWDEndcap && jExtInFWDEndcap) &&
413 !(iExtInBWDEndcap && jExtInBWDEndcap)
415 return std::numeric_limits<double>::quiet_NaN();
429 const auto iExtR = (iExtTheta >= th_fwd_brl && iExtTheta < th_bwd_brl) ? rho / sin(iExtTheta) : ((iExtTheta >= th_fwd
430 && iExtTheta < th_fwd_brl) ? zfwd / cos(iExtTheta) : zbwd / cos(iExtTheta));
431 const auto jExtR = (jExtTheta >= th_fwd_brl && jExtTheta < th_bwd_brl) ? rho / sin(jExtTheta) : ((jExtTheta >= th_fwd
432 && jExtTheta < th_fwd_brl) ? zfwd / cos(jExtTheta) : zbwd / cos(jExtTheta));
434 return sqrt((iExtR * iExtR) + (jExtR * jExtR) - 2 * iExtR * jExtR * (sin(iExtTheta) * sin(jExtTheta) * cos(iExtPhi - jExtPhi)
435 + cos(iExtTheta) * cos(jExtTheta)));
439 return std::numeric_limits<double>::quiet_NaN();
446 bool checkPList =
false;
460 bool checkPListReference =
false;
465 return (checkPList and checkPListReference);
Provides a type-safe way to pass members of the chargedStableSet set.
const ParticleType & find(int pdg) const
Returns particle in set with given PDG code, or invalidParticle if not found.
static const ParticleSet chargedStableSet
set of charged stable particles
static const ParticleType invalidParticle
Invalid particle, used internally.
Represents a particle in the DecayDescriptor.
int getPDGCode() const
Return PDG code.
std::string getFullName() const
returns the full name of the particle full_name = name:label
The DecayDescriptor stores information about a decay tree or parts of a decay tree.
bool init(const std::string &str)
Initialise the DecayDescriptor from given string.
const DecayDescriptorParticle * getMother() const
return mother.
std::vector< int > getSelectionPDGCodes()
Return list of PDG codes of selected particles.
std::vector< std::string > getSelectionNames()
Return list of human readable names of selected particles.
std::vector< const Particle * > getSelectionParticles(const Particle *particle)
Get a vector of pointers with selected daughters in the decay tree.
void setDescription(const std::string &description)
Sets the description of the module.
Class to store reconstructed particles.
bool hasExtraInfo(const std::string &name) const
Return whether the extra info with the given name is set.
int getPDGCode(void) const
Returns PDG code.
double getP() const
Returns momentum magnitude (same as getMomentumMagnitude but with shorter name)
double getExtraInfo(const std::string &name) const
Return given value if set.
StoreObjPtr< EventMetaData > m_event_metadata
The event information.
std::unique_ptr< DBObjPtr< PIDDetectorWeights > > m_DBWeights
Interface to get the database payload with the PID detector weights.
std::unordered_map< std::string, std::vector< int > > m_detToLayers
Map that associates to each detector its list of valid layers.
~TrackIsoCalculatorModule() override
Destructor, use this to clean up anything you created in the constructor.
void initialize() override
Use this to initialize resources or memory your module needs.
double getDistAtDetSurface(const Particle *iParticle, const Particle *jParticle, const std::string &detLayerName) const
Calculate the distance between the points where the two input extrapolated track helices cross the gi...
void event() override
Called once for each event.
std::unordered_map< std::string, std::string > m_detLayerToDistVariable
Map that associates to each detector layer the name of the variable representing the distance to the ...
std::string m_decayString
The name of the input charged stable particle list, or composite particle w/ charged stable daughters...
StoreObjPtr< ParticleList > m_pListTarget
The input ParticleList object for which distances are to be calculated.
std::string m_isoScoreVariable
The name of the variable representing the track isolation score in this detector.
StoreArray< Particle > m_particles
StoreArray of Particles.
std::string m_payloadName
The name of the database payload object with the MVA weights.
Const::EDetector getDetEnum(const std::string &detName) const
Get the enum type for this detector name.
std::string m_detName
The name of the detector at whose inner (cylindrical) surface we extrapolate each track's polar and a...
std::string m_pListReferenceName
The name of the input ParticleList of reference tracks.
std::unordered_map< std::string, std::string > m_detLayerToRefPartIdxVariable
Map that associates to each detector layer the name of the variable representing the mdst array index...
double getDistThreshold(Const::EDetector det, int layer) const
Get the threshold value per detctor layer for the distance to closest ext.
bool onlySelectedStdChargedInDecay()
Check whether input particle list and reference list are of a valid charged stable particle.
bool m_excludePIDDetWeights
Exclude the PID detector weights for the isolation score definition.
double getIsoScore(const Particle *iParticle) const
Define a semi-continuous variable to quantify the isolation of a standard charged particle in the giv...
DecayDescriptor m_decaydescriptor
< Decay descriptor of decays to look for.
std::unordered_map< std::string, DetSurfCylBoundaries > m_detLayerToSurfBoundaries
Map that associates to each detector layer its valid cylindrical surface's boundaries.
TrackIsoCalculatorModule()
Constructor: Sets the description, the properties and the parameters of the module.
unsigned int m_nLayers
The number of layers for the input detector.
unsigned short m_nSelectedDaughters
The number of selected daughters in the decay string.
StoreObjPtr< ParticleList > m_pListReference
The input ParticleList object of reference tracks.
bool m_useHighestProbMassForExt
If this option is set, the helix extrapolation for the target and reference particles will use the tr...
static Manager & Instance()
get singleton instance.
REG_MODULE(B2BIIConvertBeamParams)
Register the module.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Abstract base class for different kinds of events.