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