Belle II Software development
PurityCalculatorTools.h
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#pragma once
10
11#include <tracking/spacePointCreation/MCVXDPurityInfo.h>
12
13#include <framework/datastore/RelationVector.h>
14#include <mdst/dataobjects/MCParticle.h>
15
16#include <tracking/spacePointCreation/SpacePoint.h>
17//#include <vxd/dataobjects/VXDTrueHit.h>
18#include <pxd/dataobjects/PXDTrueHit.h>
19#include <svd/dataobjects/SVDTrueHit.h>
20
21#include <tracking/spacePointCreation/MapHelperFunctions.h>
22
23#include <vector>
24#include <utility> // for pair
25#include <unordered_map>
26#include <cmath> // for fabs
27
28namespace Belle2 { // make separate sub-namespace for this?
39 static bool findWeightInVector(std::vector<std::pair<int, double> >& vec, double weight)
40 {
41 const double epsilon = 1e-4; // no real need for accuracy here since weights are rather far apart!
42 return (std::find_if(vec.begin(), vec.end(),
43 [&epsilon, &weight](const std::pair<int, double>& p)
44 { return fabs(p.second - weight) <= epsilon; })
45 != vec.end());
46 }
47
54 template<typename TrueHitType>
55 static std::vector<std::pair<int, double> > getMCParticles(const Belle2::SpacePoint* spacePoint)
56 {
57 // CAUTION: getting all TrueHits here (i.e. from all StoreArrays)
58 Belle2::RelationVector<TrueHitType> trueHits = spacePoint->getRelationsTo<TrueHitType>("ALL");
59 std::vector<std::pair<int, double> > mcParticles;
60 B2DEBUG(29, "Found " << trueHits.size() << " TrueHits related to SpacePoint " << spacePoint->getArrayIndex());
61
62 for (size_t iTH = 0; iTH < trueHits.size(); ++iTH) {
63 B2DEBUG(29, "Trying to get MCParticles from TrueHit " << trueHits[iTH]->getArrayIndex() <<
64 " from Array " << trueHits[iTH]->getArrayName());
65 Belle2::MCParticle* mcPart = trueHits[iTH]->template getRelatedFrom<Belle2::MCParticle>("ALL");
66
67 int mcPartId = -1; // default value for MCPartId (not found)
68 if (mcPart != nullptr) {
69 mcPartId = mcPart->getArrayIndex();
70 B2DEBUG(29, "TrueHit is related to MCParticle " << mcPartId);
71 } else {
72 B2DEBUG(20, "Found no MCParticle related to TrueHit " << trueHits[iTH]->getArrayIndex() <<
73 " from Array " << trueHits[iTH]->getArrayName());
74 }
75 mcParticles.push_back(std::make_pair(mcPartId, trueHits.weight(iTH)));
76 }
77
78 // sort & unique to filter out double MCIds (if the relations are set correct, this only happens if more than one TrueHits point to the same MCParticle)
79 std::sort(mcParticles.begin(), mcParticles.end());
80 auto newEnd = std::unique(mcParticles.begin(), mcParticles.end(),
81 [](const std::pair<int, double>& a, const std::pair<int, double>& b) { return a.first == b.first; }
82 );
83 if (newEnd != mcParticles.end()) B2DEBUG(20,
84 "More than one TrueHits (related to one SpacePoint) are related to the same MCParticle!");
85 mcParticles.resize(std::distance(mcParticles.begin(), newEnd));
86
87 // check if there were noise Clusters in the SpacePoint
88 // only case left for PXD is missing TrueHit for underlying Cluster, everything else is covered!
89 if (spacePoint->getType() == VXD::SensorInfoBase::PXD) {
90 if (mcParticles.empty()) mcParticles.push_back(std::make_pair(-2, 1)); // if no Id in vector there is no relation to TrueHit
91 } else if (spacePoint->getType() == VXD::SensorInfoBase::SVD) { // for SVD some more tests are needed!
92 // check if there is one MCParticle that is related to both Clusters of the SpacePoint
93 if (!findWeightInVector(mcParticles, 2)) { // if not both related check which ones should have a relation and act accordingly
94 const std::pair<bool, bool>& clusters = spacePoint->getIfClustersAssigned();
95 bool uGood = clusters.first && findWeightInVector(mcParticles, 11);
96 bool vGood = clusters.second && findWeightInVector(mcParticles, 21);
97 if (!uGood && !vGood) mcParticles.push_back(std::make_pair(-2, 2)); // if both Clusters are not related -> weight is 2
98 else if (uGood && !vGood) mcParticles.push_back(std::make_pair(-2, 21)); // if only V-Cluster is not related -> weight is 21
99 else if (!uGood && vGood) mcParticles.push_back(std::make_pair(-2, 11)); // if only U-Cluster is not related -> weight is 11
100 }
101 } else {
102 B2ERROR("Unknown DetectorType in getMCParticles! This is just a notification! Needs to be handled!"); // should not happen
103 }
104
105 return mcParticles;
106 }
107
111 static void increaseClusterCounters(const Belle2::SpacePoint* spacePoint, std::array<unsigned, 3>& clusterCtr)
112 {
113 if (spacePoint->getType() == Belle2::VXD::SensorInfoBase::PXD) {
114 clusterCtr[0]++;
115 B2DEBUG(29, "SpacePoint contains PXDCluster");
116 } else {
117 std::pair<bool, bool> setClusters = spacePoint->getIfClustersAssigned();
118 if (setClusters.first) {
119 clusterCtr[1]++;
120 B2DEBUG(29, "SpacePoint contains U SVDCluster");
121 }
122 if (setClusters.second) {
123 clusterCtr[2]++;
124 B2DEBUG(29, "SpacePoint contains V SVDCluster");
125 }
126 }
127 }
128
132 static std::vector<size_t> getAccessorsFromWeight(double weight)
133 {
134 if (weight < 1.5 && weight > 0) return {0}; // weight 1 -> PXD
135 if (weight < 2.5 && weight > 0) return { 1, 2 }; // weight 2 -> both Clusters with relation to MCParticle
136 if (weight < 20 && weight > 0) return {1}; // weight 11 -> only U-Cluster related to MCParticle
137 if (weight > 20 && weight < 30) return {2}; // weight 21 -> only V-Cluster related to MCParticle
138
139 return std::vector<size_t>(); // empty vector else
140 }
141
149 static std::vector<Belle2::MCVXDPurityInfo> createPurityInfosVec(const std::vector<const Belle2::SpacePoint*>& spacePoints)
150 {
151 std::array<unsigned, 3> totalClusters = { {0, 0, 0 } };
152 // WARNING: relying on the fact here that all array entries will be initialized to 0
153 std::unordered_map<int, std::array<unsigned, 3> > mcClusters;
154
155 unsigned nClusters = 0; // NOTE: only needed for DEBUG output -> remove?
156
157 for (const Belle2::SpacePoint* spacePoint : spacePoints) {
158 B2DEBUG(29, "Now processing SpacePoint " << spacePoint->getArrayIndex() << " from Array " << spacePoint->getArrayName());
159 increaseClusterCounters(spacePoint, totalClusters);
160
161 nClusters += spacePoint->getNClustersAssigned();
162
163 std::vector<std::pair<int, double> > mcParticles;
164 if (spacePoint->getType() == VXD::SensorInfoBase::PXD) mcParticles = getMCParticles<PXDTrueHit>(spacePoint);
165 else if (spacePoint->getType() == VXD::SensorInfoBase::SVD) mcParticles = getMCParticles<SVDTrueHit>(spacePoint);
166 else if (spacePoint->getType() == VXD::SensorInfoBase::VXD) {B2DEBUG(25, "found generic spacePoint, treating it as virtualIP");}
167 else B2FATAL("Unknown DetectorType (" << spacePoint->getType() << ") in createPurityInfos! Skipping this SpacePoint " <<
168 spacePoint->getArrayIndex() << " from Array " << spacePoint->getArrayName());
169
170 for (const std::pair<int, double>& particle : mcParticles) {
171 std::vector<size_t> accessors = getAccessorsFromWeight(particle.second);
172 for (size_t acc : accessors) {
173 mcClusters[particle.first][acc]++;
174 }
175 }
176 }
177 B2DEBUG(29, "container contained " << spacePoints.size() << " SpacePoint with " << nClusters << " Clusters");
178
179 // create MCVXDPurityInfos and add them to the return vector
180 std::vector<Belle2::MCVXDPurityInfo> purityInfos;
181 for (int mcId : getUniqueKeys(mcClusters)) {
182 // cppcheck-suppress useStlAlgorithm
183 purityInfos.push_back(MCVXDPurityInfo(mcId, totalClusters, mcClusters[mcId]));
184 }
185
186 // sort in descending order before return
187 std::sort(purityInfos.begin(), purityInfos.end(),
188 [](const MCVXDPurityInfo & left, const MCVXDPurityInfo & right) { return left > right; }
189 );
190 return purityInfos;
191 }
192
201 template<typename SPContainer>
202 static std::vector<Belle2::MCVXDPurityInfo> createPurityInfos(const SPContainer* container)
203 {
204 return createPurityInfosVec(container->getHits());
205 }
206
217 template<typename SPContainer>
218 static std::vector<Belle2::MCVXDPurityInfo> createPurityInfos(const SPContainer& container)
219 {
220 return createPurityInfos(&container);
221 }
223} // end namespace Belle2
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
int getArrayIndex() const
Get 0-based index of the particle in the corresponding MCParticle list.
Definition: MCParticle.h:244
The MC VXD Purity info container class.
Class for type safe access to objects that are referred to in relations.
size_t size() const
Get number of relations.
float weight(int index) const
Get weight with index.
int getArrayIndex() const
Returns this object's array index (in StoreArray), or -1 if not found.
RelationVector< TO > getRelationsTo(const std::string &name="", const std::string &namedRelation="") const
Get the relations that point from this object to another store array.
SpacePoint typically is build from 1 PXDCluster or 1-2 SVDClusters.
Definition: SpacePoint.h:42
std::pair< bool, bool > getIfClustersAssigned() const
Returns, if u(v)-coordinate is based on cluster information.
Definition: SpacePoint.h:162
Belle2::VXD::SensorInfoBase::SensorType getType() const
Return SensorType (PXD, SVD, ...) on which the SpacePoint lives.
Definition: SpacePoint.h:145
@ VXD
Any type of VXD Sensor.
static std::vector< Belle2::MCVXDPurityInfo > createPurityInfosVec(const std::vector< const Belle2::SpacePoint * > &spacePoints)
create a vector of MCVXDPurityInfos objects for a std::vector<Belle2::SpacePoints>.
std::vector< typename MapType::key_type > getUniqueKeys(const MapType &aMap)
get the unique keys of a map (i.e.
static std::vector< std::pair< int, double > > getMCParticles(const Belle2::SpacePoint *spacePoint)
get the related MCParticles to the TrueHit.
static bool findWeightInVector(std::vector< std::pair< int, double > > &vec, double weight)
find the given weight in the given vector of pair<int,double> NOTE: the criteria for finding are rath...
static std::vector< size_t > getAccessorsFromWeight(double weight)
convert the relation weight (SpacePoint <-> TrueHit) to a type that can be used to access arrays
static void increaseClusterCounters(const Belle2::SpacePoint *spacePoint, std::array< unsigned, 3 > &clusterCtr)
increase the appropriate Cluster counter by asking the SpacePoint which type he has and which Cluster...
static std::vector< Belle2::MCVXDPurityInfo > createPurityInfos(const SPContainer *container)
create a vector of MCVXDPurityInfos objects for any given container holding SpacePoints and providing...
Abstract base class for different kinds of events.