Belle II Software  release-08-01-10
SpacePoint2TrueHitConnectorModule.cc
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 #include <tracking/modules/spacePointCreator/SpacePoint2TrueHitConnectorModule.h>
10 #include <framework/datastore/StoreObjPtr.h>
11 #include <framework/dataobjects/EventMetaData.h>
12 #include <framework/core/Environment.h> // getNumberProcesses
13 
14 #include <pxd/dataobjects/PXDCluster.h>
15 #include <svd/dataobjects/SVDCluster.h>
16 #include <mdst/dataobjects/MCParticle.h>
17 
18 #include <string>
19 #include <vector>
20 #include <cmath>
21 
22 #include <algorithm>
23 #include <unordered_map>
24 #include <tracking/spacePointCreation/MapHelperFunctions.h> // map helper stuff
25 
26 #include <TFile.h>
27 #include <TTree.h>
28 #include <Math/Vector3D.h>
29 
30 using namespace Belle2;
31 
32 
33 REG_MODULE(SpacePoint2TrueHitConnector); // register the modules
34 
36  Module()
37 {
38  setDescription("Module that tries to find the appropriate TrueHit to each SpacePoint and to register a relation between them for making MC information for SpacePoints more easily accesible for Modules that need it. Module can also be used to filter out 'fishy' SpacePoints.");
40 
41  addParam("storeSeperate", m_PARAMstoreSeparate,
42  "Set to false if you do not want to create seperate StoreArrays for processed SpacePoints. (i.e. a relation from SpacePoint to TrueHit will be set in the passed StoreArray. NOTE: this StoreArray will contain SpacePoints with a relation to TrueHits and such without after this module). The Names of the output StoreArrays will be the names of the input StoreArrays with 'outputSuffix' (module parameter) appended to them",
43  true);
44 
45  addParam("registerAll", m_PARAMregisterAll,
46  "If set to true, the module simply registers a relation for all TrueHits that are related to a SpacePoint (resp. its Clusters). In this way the module can be used to find all related TrueHits and then the user can decide what to do with these TrueHits (otherwise this module does some decision making). Setting this to true means that all checks (e.g. 'minWeight', 'maxPosSigma', ...) are ommitted! NOTE that some of the information is lost in this way (e.g. how many of the Clusters of a SpacePoint have been related to a TrueHit)!",
47  false);
48 
49  addParam("positionAnalysis", m_PARAMpositionAnalysis,
50  "Analyze the positions of SpacePoints and corresponding TrueHits. NOTE: if enabled a root file gets created!", false);
51 
52  addParam("requirePrimary", m_PARAMrequirePrimary,
53  "Set to true if only relations to TrueHits that are related to a primary particle should get registered.", false);
54 
55  addParam("requireProximity", m_PARAMrequireProximity,
56  "Require that the TrueHit is close to the SpacePoint (in local coordinates). The meaning of 'close' can be defined with the parameters 'maxPosSigma' and 'maxGlobalPosDiff'.",
57  true);
58 
59  std::vector<std::string> defaultInList; // default list for input StoreArrays
60  defaultInList.push_back(std::string(""));
61  addParam("TrueHitNames", m_PARAMtrueHitNames,
62  "Container names of TrueHits. NOTE: need one name per 'DetectorType' (i.e. unique entries in 'DetectorType)!", defaultInList);
63  addParam("SpacePointNames", m_PARAMspacePointNames, "Container names of SpacePoints.", {"SVDSpacePoints", "PXDSpacePoints"});
64  addParam("DetectorTypes", m_PARAMdetectorTypes,
65  "detector types to determine which entries in 'TrueHitNames' and 'SpacePointNames' belong to which detector type. Entries have to be 'SVD' or 'PXD'. NOTE: if more 'SpacePointNames' than 'DetectorTypes' get passed, the last entry in 'DetectorTypes' is assumed to be valid for all remaining 'SpacePointNames'!");
66  addParam("ClusterNames", m_PARAMclusterNames,
67  "Container names of Clusters. NOTE: need one name per 'DetectorType' (i.e. unique entries in 'DetectorType')!", defaultInList);
68 
69  std::vector<std::string> defaultRootFName = { "PositionAnalysis", "RECREATE" };
70  addParam("rootFileName", m_PARAMrootFileName,
71  "Filename and write-mode ('RECREATE' or 'UPDATE'). If given more than 2 strings this module will cause termination",
72  defaultRootFName);
73 
74  addParam("outputSuffix", m_PARAMoutputSuffix,
75  "Suffix that will be appended to the container names if 'storeSeperate' is set to true", std::string("_relTH"));
76 
77  addParam("maxGlobalPosDiff", m_PARAMmaxGlobalDiff,
78  "max difference of global position coordinates between TrueHit and SpacePoint (in each direction) in cm.", 0.05);
79 // addParam("maxLocalPosDiff", m_PARAMmaxLocalDiff, "max difference of local position coordinates between TrueHit and SpacePoint (in U & V direction) in cm. NOTE: the default value is still subject to tuning and finding the appropriate value!", 0.01);
80 
81  addParam("maxPosSigma", m_PARAMmaxPosSigma, "Define the maximum local position difference in units of PitchSize / sqrt(12).", 4.);
82  addParam("minWeight", m_PARAMminWeight,
83  "Define a minimal weight a relation between a Cluster and a TrueHit has to have for the TrueHit to be considered as possible candidate.",
84  0.);
85 
86  // initialize all counters
88  m_rootFilePtr = nullptr;
89  m_treePtr = nullptr;
90 
91  if (m_PARAMpositionAnalysis == true and Environment::Instance().getNumberProcesses() > 0) {
92  B2WARNING(
93  "SpacePoint2TrueHitConnector::initialize: parameter positionAnalysis (and therefore root-output) is enabled and basf2 is running in multi-threaded mode - this can cause nondeterministic behavior! "
94  << "\n"
95  << " you can suppress multi-threading for this module by writing:"
96  << "\n"
97  << "main.add_module('SpacePoint2TrueHitConnector').set_property_flags(0) "
98  << "\n"
99  << "into the steering file!");
100  }
101 }
102 
103 // ================================================================ INITIALIZE ====================================================
105 {
106  B2INFO("SpacePoint2TrueHitConnector -------------------------- initialize --------------------------------");
107 
108  m_nContainers = m_PARAMspacePointNames.size(); // get number of passed arrays
109  unsigned int nTHNames = m_PARAMtrueHitNames.size();
110  unsigned int nDetTypes = m_PARAMdetectorTypes.size();
111  unsigned int nClNames = m_PARAMclusterNames.size();
112  if (m_nContainers < nTHNames || m_nContainers < nDetTypes || m_nContainers < nClNames) {
113  B2FATAL("Passed " << nTHNames << " TrueHitNames and " << nDetTypes << " DetectorTypes but number of passed SpacePointArrays is " <<
114  m_nContainers);
115  }
116  if ((nTHNames != nDetTypes) || (nClNames != nTHNames)) {
117  B2FATAL("Passed " << nTHNames << " TrueHitNames and " << nClNames << "ClusterNames but " << nDetTypes << " DetectorTypes!");
118  }
119 
120  for (unsigned int i = 0; i < m_nContainers; ++i) {
121  if (i < nDetTypes) { // handle the detector types
122  std::string detType = m_PARAMdetectorTypes.at(i);
123  if (detType.compare(std::string("SVD")) != 0 && detType.compare(std::string("PXD")) != 0) {
124  B2FATAL("Found entry " << detType << " in DetectorTypes, but only 'PXD' and 'SVD' are allowed!");
125  }
126  if (detType.compare(std::string("SVD")) == 0) {
127  m_detectorTypes.push_back(c_SVD);
132  } else {
133  m_detectorTypes.push_back(c_PXD);
138  }
139  } else { m_detectorTypes.push_back(m_detectorTypes.at(i - 1)); } // add the last entry again
140 
141  m_inputSpacePoints.push_back(std::make_pair(StoreArray<SpacePoint>(m_PARAMspacePointNames.at(i)), m_detectorTypes.at(i)));
142  m_inputSpacePoints.at(i).first.isRequired();
143 
144  // add counters
145  m_SpacePointsCtr.push_back(0);
146  m_nRelTrueHitsCtr.push_back(std::array<unsigned int, 5>());
147  m_noClusterCtr.push_back(0);
148  m_noTrueHitCtr.push_back(0);
149  m_regRelationsCtr.push_back(0);
150  m_ghostHitCtr.push_back(0);
151  m_rejectedRelsCtr.push_back(0);
152  }
153 
154  if (m_PARAMstoreSeparate) {
155  if (m_PARAMoutputSuffix.empty()) {
156  B2WARNING("'outputSuffix' is empty and 'storeSeperate' is set to true. This would lead to StoreArrays with the same name. Resetting to 'outputSuffix' to '_relTH'!");
157  m_PARAMoutputSuffix = "_relTH";
158  }
159 
160  for (unsigned int i = 0; i < m_nContainers; ++i) {
161  std::string name = m_inputSpacePoints.at(i).first.getName() + m_PARAMoutputSuffix;
164 
165  // register relations (detector dependent)
166  if (m_inputSpacePoints.at(i).second == c_SVD) {
169  } else {
172  }
173  }
174  } else {
175  for (unsigned int i = 0; i < m_nContainers; ++i) {
176  if (m_inputSpacePoints.at(i).second == c_SVD) {
178  } else {
180  }
181  }
182  }
183 
184  m_maxGlobalDiff = m_PARAMmaxGlobalDiff * m_PARAMmaxGlobalDiff; // only comparing squared values in module!
185 // m_PARAMmaxLocalDiff *= m_PARAMmaxLocalDiff;
186 
187  if (m_PARAMmaxPosSigma < 0) {
188  B2WARNING("'maxPosSigma' is set to a value below 0: " << m_PARAMmaxPosSigma << "! Resetting to default (4)!");
189  m_PARAMmaxPosSigma = 4.;
190  }
191 
193 }
194 
195 // ========================================================== EVENT ===============================================================
197 {
198  StoreObjPtr<EventMetaData> eventMetaDataPtr("EventMetaData", DataStore::c_Event);
199  const int eventCtr = eventMetaDataPtr->getEvent();
200  B2DEBUG(20, "SpacePoint2TrueHitConnector::event(). Processing event " << eventCtr << " -----------------------");
201 
202  if (m_PARAMpositionAnalysis) m_rootVariables = RootVariables(); // clear the rootVariables for every event
203 
204  // loop over all containers
205  for (m_iCont = 0; m_iCont < m_nContainers; ++m_iCont) {
206  StoreArray<SpacePoint> spacePoints = m_inputSpacePoints.at(m_iCont).first;
207  const int nSpacePoints = spacePoints.getEntries();
208  e_detTypes detType = m_inputSpacePoints.at(m_iCont).second;
209  std::string detTypeStr = detType == c_SVD ? "SVD" : "PXD";
210  B2DEBUG(20, "Found " << nSpacePoints << " SpacePoints in Array " << m_inputSpacePoints.at(m_iCont).first.getName() <<
211  " for this event. detType: " << detTypeStr);
212 
213  m_SpacePointsCtr.at(m_iCont) += nSpacePoints;
214 
215  for (int iSP = 0; iSP < nSpacePoints; ++iSP) {
216  SpacePoint* spacePoint = spacePoints[iSP];
217  B2DEBUG(21, "Processing SpacePoint " << iSP << " from " << nSpacePoints);
218 
219  baseMapT trueHitMap = processSpacePoint<baseMapT>(spacePoint, detType);
220  if (trueHitMap.empty()) continue; // next SpacePoint if something went wrong
221 
222  unsigned int nUniqueTHs = getUniqueSize(trueHitMap);
223  B2DEBUG(23, "Found " << nUniqueTHs << " TrueHits (unique) related to SpacePoint " << spacePoint->getArrayIndex() << " from Array "
224  << spacePoint->getArrayName());
225  unsigned int iRels = nUniqueTHs > 4 ? 4 : nUniqueTHs - 1;
226  m_nRelTrueHitsCtr.at(m_iCont).at(iRels)++;
227 
228  // print the complete map if the debug level is set high enough
229  if (LogSystem::Instance().isLevelEnabled(LogConfig::c_Debug, 350, PACKAGENAME())) {
230  std::string mapCont = printMap(trueHitMap);
231  B2DEBUG(24, "The TrueHits and their weights for spacePoint " << spacePoint->getArrayIndex() << ": " + mapCont);
232  }
233 
234  int thIndex = -1; // declare negative and only assign a value if ONE relation gets registered! (see doc of positionAnalysis)
235  if (m_PARAMregisterAll) {
236  registerAllRelations(spacePoint, trueHitMap, detType);
237  } else { // find THE ONE TrueHit (to rule them all, one TrueHit to find them all ...)
238  // COULDDO: wrap this up in a function
239  std::pair<VXDTrueHit*, double> trueHitwWeight;
240 
241  if (detType == c_PXD) trueHitwWeight = getTHwithWeight<baseMapT, PXDTrueHit>(trueHitMap, m_PXDTrueHits, spacePoint, c_PXD);
242  else trueHitwWeight = getTHwithWeight<baseMapT, SVDTrueHit>(trueHitMap, m_SVDTrueHits, spacePoint, c_SVD);
243 
244  if (trueHitwWeight.first != nullptr) {
245  registerOneRelation(spacePoint, trueHitwWeight, detType);
246  thIndex = trueHitwWeight.first->getArrayIndex();
247  } else {
248  B2DEBUG(20, "Could not relate one TrueHit to SpacePoint " << spacePoint->getArrayIndex() << ".");
250  }
251  }
252 
253  if (m_PARAMpositionAnalysis) { positionAnalysis(spacePoint, trueHitMap, thIndex, detType); }
254  } // end loop SpacePoints
255  } // end loop containers
256  if (m_PARAMpositionAnalysis) { m_treePtr->Fill(); }
257 }
258 
259 // ================================================================ TERMINATE ======================================================
261 {
262  unsigned int sumSpacePoints = accumulate(m_SpacePointsCtr.begin(), m_SpacePointsCtr.end(), 0);
263  unsigned int sumRelations = accumulate(m_regRelationsCtr.begin(), m_regRelationsCtr.end(), 0);
264 
265  B2RESULT("SpacePoint2TrueHitConnector: Got " << sumSpacePoints << " SpacePoints in " << m_nContainers <<
266  " containers and registered " << sumRelations << " relations to TrueHits");
267  if (LogSystem::Instance().isLevelEnabled(LogConfig::c_Debug, 1, PACKAGENAME())) {
268  std::stringstream contSumm;
269  contSumm << "Container-wise summary: \n";
270 
271  for (unsigned int iCont = 0; iCont < m_nContainers; ++iCont) {
272  contSumm << "In Container " << iCont << " (container name: " << m_inputSpacePoints[iCont].first.getName() << ") " <<
273  m_SpacePointsCtr[iCont] << " SpacePoints were contained. " << m_regRelationsCtr[iCont] <<
274  " relations were registered.\nNumber of related TrueHits to a SpacePoint are:\n";
275  for (unsigned int i = 0; i < m_nRelTrueHitsCtr[iCont].size() - 1; ++i) { contSumm << i + 1 << " related TrueHits to a SpacePoint : " << m_nRelTrueHitsCtr[iCont].at(i) << "\n"; }
276  contSumm << " more than 4 related TrueHits to a SpacePoint: " << m_nRelTrueHitsCtr[iCont].at(4) << "\n"; // WARNING: hardcoded
277  contSumm << m_rejectedRelsCtr.at(iCont) << " SpacePoints did not get a relation, " << m_ghostHitCtr.at(
278  iCont) << " were probably ghost hits in this container!\n";
279  contSumm << m_noTrueHitCtr[iCont] << " SpacePoints had no relation to a TrueHit at all.\n";
280  }
281  B2DEBUG(20, contSumm.str());
282 
283  if (!m_PARAMregisterAll) {
284  // TODO: do this containerwise
285  std::stringstream furtherSummary;
286  furtherSummary << "Ommited Relations because of weight < " << m_PARAMminWeight << ": " << m_weightTooSmallCtr << "\n";
287  furtherSummary << "Rejected Relations because of non primary particle: " << m_rejectedNoPrimaryCtr;
288 // furtherSummary << "Summary for all containers:\n";
289 // furtherSummary << "possible/accepted relations for cases:\n";
290 // furtherSummary << m_all2WTHCtr << "/" << m_accAll2WTHCtr << " SP with THs (more than one) with all THs having two weights\n";
291 // furtherSummary << m_single2WTHCtr << "/" << m_accSingle2WTHCtr << " SP with THs (more than one) with only one TH having two weights\n";
292 // furtherSummary << m_nonSingle2WTHCtr << "/" << m_accNonSingle2WTHCtr << " SP with THs (more than one) with more than one but not all THs having two weights\n";
293 // furtherSummary << "In " << m_oneCluster2THCtr << " cases there was a SP with only one Cluster but more than one related TrueHits";
294  B2DEBUG(20, furtherSummary.str());
295  }
296  }
297 
299 
300 // B2INFO("total number of weights: " << m_totWeightsCtr << " of which " << m_negWeightCtr << " were negative")
301 // B2INFO("m_moreThan2Weights = " << m_moreThan2Weights);
302 }
303 
304 // ====================================================== PROCESS SPACEPOINT ======================================================
305 template<typename MapType>
307 {
308  B2DEBUG(23, "Processing SpacePoint " << spacePoint->getArrayIndex() << " from Array " << spacePoint->getArrayName());
309  MapType trueHitMap;
310  try {
311  if (detType == c_PXD) {
312  trueHitMap = getRelatedTrueHits<MapType, PXDCluster, PXDTrueHit>(spacePoint, m_PXDClusters.getName(), m_PXDTrueHits.getName());
313  } else {
314  trueHitMap = getRelatedTrueHits<MapType, SVDCluster, SVDTrueHit>(spacePoint, m_SVDClusters.getName(), m_SVDTrueHits.getName());
315  }
316  } catch (NoClusterToSpacePoint& anE) {
317  B2WARNING("Caught an exception while trying to relate SpacePoints and TrueHits: " << anE.what());
318  m_noClusterCtr.at(m_iCont)++;
319  } catch (...) { // catch the rest
320  B2ERROR("Caught undefined exception while trying to relate SpacePoints and TrueHits");
321  throw; // throw further (maybe it is caught somewhere else)
322  }
323 
324  B2DEBUG(25, "trueHitMap.size() before return in processSpacePoint: " << trueHitMap.size());
325  return trueHitMap;
326 }
327 
329 template<typename MapType, typename ClusterType, typename TrueHitType>
331  std::string trueHitName)
332 {
333  MapType trueHitsMap; // map to be filled with indices (keys) and weights (values)
334 
335  RelationVector<ClusterType> spacePointClusters = spacePoint->getRelationsTo<ClusterType>(clusterName);
336  if (spacePointClusters.size() == 0) {
337  B2DEBUG(20, "Found no related Cluster for SpacePoint " << spacePoint->getArrayIndex() << " from Array " <<
338  spacePoint->getArrayIndex());
339  throw NoClusterToSpacePoint();
340  }
341  B2DEBUG(24, "Found " << spacePointClusters.size() << " related Clusters to SpacePoint " << spacePoint->getArrayIndex() <<
342  " from Array " << spacePoint->getArrayName());
343 
344  // loop over all Clusters, get all TrueHits from them and add the information to the map
345  short noTrueHits = 0;
346  for (size_t iCl = 0; iCl < spacePointClusters.size(); ++iCl) {
347 
348  const ClusterType* cluster = spacePointClusters[iCl];
349  RelationVector<TrueHitType> clusterTrueHits = cluster->template getRelationsTo<TrueHitType>(trueHitName);
350  if (clusterTrueHits.size() == 0) {
351  B2DEBUG(20, "Found no related TrueHit for Cluster " << cluster->getArrayIndex() << " contained by SpacePoint " <<
352  spacePoint->getArrayIndex() << " from Array " << spacePoint->getArrayName());
353  noTrueHits++;
354  } else {
355  B2DEBUG(26, "Found " << clusterTrueHits.size() << " related TrueHits to Cluster " << cluster->getArrayIndex() << " from Array " <<
356  cluster->getArrayName());
357 
358  for (unsigned int i = 0; i < clusterTrueHits.size(); ++i) { // 'TrueHit' loop
359  if ((clusterTrueHits.weight(i) < m_PARAMminWeight) && !m_PARAMregisterAll) {
361  continue; // not take into account relations with too little weight
362  }
363  int index = clusterTrueHits[i]->getArrayIndex();
364  if (trueHitsMap.find(index) == trueHitsMap.end()) { // create entry only if it is not already in the map
365  trueHitsMap[index] = TrueHitInfo(index);
366  B2DEBUG(29, "Added new TrueHitInfo to map. Index " << index);
367  }
368  if (spacePointClusters.weight(iCl) > 0) {
369  trueHitsMap[index].setUWeight(clusterTrueHits.weight(i));
370  B2DEBUG(29, "Added UCluster to TrueHitInfo with index " << index);
371  } else {
372  trueHitsMap[index].setVWeight(clusterTrueHits.weight(i));
373  B2DEBUG(29, "Added VCluster to TrueHitInfo with index " << index);
374  }
375  }
376  }
377  }
378  // check if there was no Cluster with a related TrueHit -> then throw
379  if (noTrueHits == spacePoint->getNClustersAssigned()) {
380  m_noTrueHitCtr[m_iCont]++; // increase counter for current container
381  }
382  return trueHitsMap;
383 }
384 
385 // ================================================================= INITIALIZE COUNTERS ==========================================
387 {
388  // NEW
389  for (unsigned int i = 0; i < m_SpacePointsCtr.size(); ++i) {
390  m_SpacePointsCtr.at(i) = 0;
391  m_regRelationsCtr.at(i) = 0;
392  m_noClusterCtr.at(i) = 0;
393  m_ghostHitCtr.at(i) = 0;
394  m_noTrueHitCtr.at(i) = 0;
395  m_rejectedRelsCtr.at(i) = 0;
396 
397  for (unsigned int j = 0; j < m_nRelTrueHitsCtr.at(i).size(); ++j) { m_nRelTrueHitsCtr.at(i).at(j) = 0; }
398  }
399 
402 
403  // initialize the following here because of cppcheck complaining (not initialized in constructor)
404  m_nContainers = 0;
405  m_maxGlobalDiff = 0.;
406  m_iCont = 0;
407 
408 // m_negWeightCtr = 0;
409 // m_totWeightsCtr = 0;
410 // m_moreThan2Weights = 0;
411 //
412 // m_single2WTHCtr = 0;
413 // m_nonSingle2WTHCtr = 0;
414 // m_all2WTHCtr = 0;
415 // m_accSingle2WTHCtr = 0;
416 // m_accNonSingle2WTHCtr = 0;
417 // m_accAll2WTHCtr = 0;
418 //
419 // m_oneCluster2THCtr = 0;
420 //
421 
422 }
423 
424 // ===================================================== REGISTER ALL RELATIONS ===================================================
425 template<typename MapType>
427 {
428  B2DEBUG(23, "Registering all possible relations for SpacePoint " << spacePoint->getArrayIndex() << " from Array " <<
429  spacePoint->getArrayName() << ". storeSeparate is set to " << m_PARAMstoreSeparate);
430  SpacePoint* newSP = spacePoint; // declaring pointer here, getting new pointer if storeSeparate is true
431 
432  if (m_PARAMstoreSeparate) { // if storing in separate Array, re-register the relations to the Clusters first
433  newSP = m_outputSpacePoints.at(m_iCont).appendNew(*spacePoint);
434  B2DEBUG(23, "Added new SpacePoint to Array " << m_outputSpacePoints[m_iCont].getName() << ".");
435  if (detType == c_PXD) reRegisterClusterRelations<PXDCluster>(spacePoint, newSP, m_PXDClusters.getName());
436  else reRegisterClusterRelations<SVDCluster>(spacePoint, newSP, m_SVDClusters.getName());
437  }
438 
439  std::vector<TrueHitInfo> trueHitInfos = getAllValues(trueHitMap);
440  // sort by the number of related Clusters first and than by weight (descending order)
441  std::sort(trueHitInfos.begin(), trueHitInfos.end());
442 
443  for (const TrueHitInfo& info : trueHitInfos) {
444  if (detType == c_PXD) registerTrueHitRelation<PXDTrueHit>(newSP, info.m_Id, 1, m_PXDTrueHits); // only one Cluster for PXDs!
445  else { // for SVD relation weight is depending on which Cluster is related to TrueHit!
446  double weight = calculateRelationWeight(info, spacePoint);
447  registerTrueHitRelation<SVDTrueHit>(newSP, info.m_Id, weight, m_SVDTrueHits);
448  }
449  }
450 }
451 
452 // =============================================== REGISTER ONE RELATION ==========================================================
453 template<typename TrueHitType>
455  std::pair<TrueHitType*, double> trueHitwWeight, e_detTypes detType)
456 {
457  TrueHitType* trueHit = trueHitwWeight.first;
458  B2DEBUG(23, "Registering relation to TrueHit " << trueHit->getArrayIndex() << " from Array " << trueHit->getArrayName());
459  SpacePoint* newSP = spacePoint; // declaring pointer here, getting new pointer if storeSeparate ist true
460 
461  if (m_PARAMstoreSeparate) { // if storing in separate Array, re-register the relations to the Clusters first
462  newSP = m_outputSpacePoints.at(m_iCont).appendNew(*spacePoint);
463  B2DEBUG(23, "Added new SpacePoint to Array " << m_outputSpacePoints[m_iCont].getName() << ".");
464  if (detType == c_PXD) reRegisterClusterRelations<PXDCluster>(spacePoint, newSP, m_PXDClusters.getName());
465  else reRegisterClusterRelations<SVDCluster>(spacePoint, newSP, m_SVDClusters.getName());
466  }
467 
468  newSP->addRelationTo(trueHit, trueHitwWeight.second);
470  B2DEBUG(23, "Added Relation to TrueHit " << trueHit->getArrayIndex() << " from Array " << trueHit->getArrayName() <<
471  " for SpacePoint " << spacePoint->getArrayIndex() << " (weight = " << trueHitwWeight.second << ")");
472 }
473 
474 // ========================================================= REREGISTER CLUSTER RELATIONS =========================================
475 template<typename ClusterType>
477  Belle2::SpacePoint* newSpacePoint, std::string clusterName)
478 {
479  B2DEBUG(27, "Registering the Relations to Clusters of SpacePoint " << origSpacePoint->getArrayIndex() << " in Array " <<
480  origSpacePoint->getArrayName() << " for SpacePoint " << newSpacePoint->getArrayIndex() << " in Array " <<
481  newSpacePoint->getArrayName());
482 
483  std::vector<std::pair<ClusterType*, double> > clustersAndWeights = getRelatedClusters<ClusterType>(origSpacePoint, clusterName);
484  for (auto aCluster : clustersAndWeights) {
485  newSpacePoint->addRelationTo(aCluster.first, aCluster.second);
486  B2DEBUG(27, "Registered Relation to Cluster " << aCluster.first->getArrayIndex() << " with weight " << aCluster.second);
487  }
488 }
489 
490 // =========================================================== GET RELATED CLUSTERS ===============================================
491 template<typename ClusterType>
492 std::vector<std::pair<ClusterType*, double> > SpacePoint2TrueHitConnectorModule::getRelatedClusters(Belle2::SpacePoint* spacePoint,
493  std::string clusterName)
494 {
495  std::vector<std::pair<ClusterType*, double> > indsAndWeights;
496  RelationVector<ClusterType> relClusters = spacePoint->getRelationsTo<ClusterType>(clusterName);
497 
498  for (unsigned int iCl = 0; iCl < relClusters.size(); ++iCl) {
499  indsAndWeights.push_back(std::make_pair(relClusters[iCl], relClusters.weight(iCl)));
500  }
501 
502  // safety measure, should not / cannot happen (checked before)
503  if (indsAndWeights.empty()) { B2ERROR("No Clusters related to SpacePoint " << spacePoint->getArrayIndex() << "!"); }
504 
505  return indsAndWeights;
506 }
507 
508 // ====================================================== REGISTER TRUEHIT RELATIONS ==============================================
509 template<typename TrueHitType>
512 {
513  TrueHitType* trueHit = trueHits[index];
514  spacePoint->addRelationTo(trueHit, weight);
515  m_regRelationsCtr.at(m_iCont)++; // increase counter of registered relations for this container
516  B2DEBUG(23, "Added Relation to TrueHit " << index << " from Array " << trueHits.getName() << " for SpacePoint " <<
517  spacePoint->getArrayIndex() << " (weight = " << weight << ")");
518 }
519 
520 // ====================================================== POSITION ANALYSIS =======================================================
521 // TODO: debug output
522 template<typename MapType>
524  const int& index, e_detTypes detType)
525 {
526  B2DEBUG(28, "Doing position analysis for SpacePoint " << spacePoint->getArrayIndex() << " from Array " <<
527  spacePoint->getArrayName());
528  simpleBitfield<unsigned short int> relationStatus;
529 
530  // TODO TODO TODO TODO TODO TODO TODO: remove if not needed, only for tessting at the moment (i.e. do not commit)
531  std::pair<unsigned short int, unsigned short int> clusterSizes = getClusterSizes(spacePoint, detType);
532  std::pair<double, double> positionError = getLocalError(spacePoint);
533  // TODO TODO TODO TODO TODO TODO TODO: remove if not needed, only for tessting at the moment (i.e. do not commit)
534 
535  // do some checks and set the relationStatus
536  std::pair<bool, bool> setUV = spacePoint->getIfClustersAssigned();
537  if (setUV.first) relationStatus.addStatus(c_SpacePointU);
538  if (setUV.second) relationStatus.addStatus(c_SpacePointV);
539 
540  const std::vector<TrueHitInfo> trueHitInfos = getAllValues(trueHitMap);
541  unsigned int nRelations = trueHitInfos.size();
542  if (nRelations != 1) relationStatus.addStatus(c_nonUniqueRelation);
543  else relationStatus.addStatus(c_clearHit); // TODO: check if this is according to the definition of cleanHit
544 
545  B2DEBUG(29, "SpacePoint has assigned U: " << setUV.first << ", V: " << setUV.second << ". Possible TrueHits: " << nRelations);
546 
547  std::pair<double, double> spLocalPos = getLocalPos(spacePoint);
548  unsigned short int vxdId = spacePoint->getVxdID();
549  short nClusters = spacePoint->getNClustersAssigned();
550 
551  // loop over all TrueHitInfos and check if it is a ghostHit, and if a noise hit is contained in the SpacePoint
552  bool onceU = false, onceV = false; // check if both Clusters are at least used once
553  bool twoClusters = false;
554  for (const TrueHitInfo& info : trueHitInfos) {
555  onceU = onceU || info.m_U; // if U is set for one of the possible TrueHits, onceU is true after this loop
556  onceV = onceV || info.m_V;
557  twoClusters = twoClusters || (info.getNClusters() == 2); // if one of the TrueHits has two Clusters in the SpacePoint -> true
558  }
559  bool allSet = onceU && onceV;
560 
561  if (nClusters > 1) { // at this stage noise Clusters and ghostHits can only appear if there are two Clusters in the SpacePoint
562  if (!allSet) relationStatus.addStatus(c_noiseCluster);
563  if (allSet && !twoClusters) relationStatus.addStatus(c_ghostHit);
564  }
565 
566  // get the status that has been set until now as from now on it can differ for every relation
567  unsigned short int overAllStatus = relationStatus.getStatus();
568 
569  for (const TrueHitInfo& info : trueHitInfos) {
570  relationStatus.setStatus(overAllStatus); // reset status
571  VXDTrueHit* trueHit;
572  if (detType == c_SVD) { trueHit = m_SVDTrueHits[info.m_Id]; }
573  else { trueHit = m_PXDTrueHits[info.m_Id]; }
574  std::pair<ROOT::Math::XYZVector, ROOT::Math::XYZVector> trueHitPos = getTrueHitPositions(trueHit);
575 
576  double weightU = info.m_wU;
577  double weightV = info.m_wV;
578 
579  MCParticle* mcParticle = trueHit->getRelatedFrom<MCParticle>("ALL");
580  if (mcParticle != nullptr) {
581  if (mcParticle->hasStatus(MCParticle::c_PrimaryParticle)) relationStatus.addStatus(c_primaryParticle);
582  }
583 
584  if (info.m_Id == index) relationStatus.addStatus(c_registeredRelation);
585 
586  m_rootVariables.SpacePointULocal.push_back(spLocalPos.first);
587  m_rootVariables.SpacePointVLocal.push_back(spLocalPos.second);
588  m_rootVariables.SpacePointXGlobal.push_back(spacePoint->X());
589  m_rootVariables.SpacePointYGlobal.push_back(spacePoint->Y());
590  m_rootVariables.SpacePointZGlobal.push_back(spacePoint->Z());
591 
592  m_rootVariables.TrueHitULocal.push_back(trueHitPos.first.X());
593  m_rootVariables.TrueHitVLocal.push_back(trueHitPos.first.Y());
594  m_rootVariables.TrueHitXGlobal.push_back(trueHitPos.second.X());
595  m_rootVariables.TrueHitYGlobal.push_back(trueHitPos.second.Y());
596  m_rootVariables.TrueHitZGlobal.push_back(trueHitPos.second.Z());
597 
598  m_rootVariables.NRelations.push_back(nRelations);
599  m_rootVariables.RelationStatus.push_back(relationStatus.getStatus());
600  m_rootVariables.WeightU.push_back(weightU);
601  m_rootVariables.WeightV.push_back(weightV);
602  m_rootVariables.HitVxdID.push_back(vxdId);
603 
604  // TODO TODO TODO TODO TODO TODO TODO: remove if not needed, only for tessting at the moment (i.e. do not commit)
605  m_rootVariables.ClusterSizeU.push_back(clusterSizes.first);
606  m_rootVariables.ClusterSizeV.push_back(clusterSizes.second);
607  m_rootVariables.SpacePointErrorU.push_back(positionError.first);
608  m_rootVariables.SpacePointErrorV.push_back(positionError.second);
609  m_rootVariables.SpacePointErrorX.push_back(spacePoint->getPositionError().X());
610  m_rootVariables.SpacePointErrorY.push_back(spacePoint->getPositionError().Y());
611  m_rootVariables.SpacePointErrorZ.push_back(spacePoint->getPositionError().Z());
612  // TODO TODO TODO TODO TODO TODO TODO: remove if not needed, only for tessting at the moment (i.e. do not commit)
613 
614  B2DEBUG(29, "Branch contents of this entry:\nSPLocalU: " << spLocalPos.first << ". SPLocalV: " << spLocalPos.second << "\n" << \
615  "SPGlobalX: " << spacePoint->X() << ", SPGlobalY: " << spacePoint->Y() << ", SPGlobalZ " << spacePoint->Z() << "\n" << \
616  "THLocalU: " << trueHitPos.first.X() << ", THLocalV: " << trueHitPos.first.Y() << "\n" << \
617  "THGlobalX: " << trueHitPos.second.X() << ", THGlobalY: " << trueHitPos.second.Y() << ", THGlobalZ: " << trueHitPos.second.Z() <<
618  "\n" << \
619  "weight1: " << weightU << ", weight2: " << weightV << ", VxdID: " << vxdId << ", nRelations: " << nRelations << ", relStatus: " <<
620  relationStatus.getStatus());
621  }
622 }
623 
624 // ====================================================== GET TH WITH WEIGHT ======================================================
625 template<typename MapType, typename TrueHitType>
626 std::pair<TrueHitType*, double>
628  Belle2::SpacePoint* spacePoint, e_detTypes detType)
629 {
630  std::vector<TrueHitInfo> trueHitInfos = getAllValues(aMap);
631  std::pair<TrueHitType*, double> THwithWeight(nullptr, 0.0); // default return value
632  // return nullptr pointer and zero weight if there is no TrueHit (safety measure that should not actually be needed!)
633  if (trueHitInfos.empty()) return THwithWeight;
634  std::sort(trueHitInfos.begin(), trueHitInfos.end()); // sort to have best candidates at beginning
635 
636  short nClusters = spacePoint->getNClustersAssigned();
637  size_t nRelations = trueHitInfos.size(); // get the number of possible relations
638 
639  B2DEBUG(23, "Trying to select one TrueHit for SpacePoint " << spacePoint->getArrayIndex() << " from Array " <<
640  spacePoint->getArrayName() << ". SpacePoint has " << nClusters << " Clusters.");
641  B2DEBUG(25, "There are " << nRelations << " possible candidates.");
642 
643  // very verbose output only to have a look on why these TrueHits could be in the same SpacePoint, COULDDO: wrap up in function
644  if (LogSystem::Instance().isLevelEnabled(LogConfig::c_Debug, 999, PACKAGENAME())) {
645  std::stringstream output;
646  output << "The candidates are: ";
647  for (auto& info : trueHitInfos) { output << info; }
648  B2DEBUG(29, output.str());
649 
650  std::pair<double, double> spacePointLocal = getLocalPos(spacePoint);
651  std::pair<bool, bool> assignedLocal = spacePoint->getIfClustersAssigned();
652 
653  B2DEBUG(29, "SpacePoint " << spacePoint->getArrayIndex() << " U: " << spacePointLocal.first << " V: " << spacePointLocal.second <<
654  " assigned: " << assignedLocal.first << ", " << assignedLocal.second);
655 
656  std::vector<int> uniqueKeys = getUniqueKeys(aMap);
657  for (int key : uniqueKeys) {
658  TrueHitType* trueHit = trueHits[key];
659  // NOTE: assuming here that there is only one MCParticle to each TrueHit
660  MCParticle* mcParticle = trueHit->template getRelatedFrom<MCParticle>("ALL");
661 
662  int mcPartId = -1, pdgCode = 0;
663  bool primary = false;
664 
665  if (mcParticle != nullptr) {
666  mcPartId = mcParticle->getArrayIndex();
667  primary = mcParticle->hasStatus(MCParticle::c_PrimaryParticle);
668  pdgCode = mcParticle->getPDG();
669  }
670 
671  B2DEBUG(29, "TrueHit " << key << " U: " << trueHit->getU() << ", V: " << trueHit->getV() << " mc Particle Id: " << mcPartId <<
672  ", primary " << primary << ", pdg: " << pdgCode);
673  }
674  }
675 
676  // loop over all TrueHitInfos and check if the number of related Clusters is equal to the number of the number of the assigned
677  // Clusters in the SpacePoint -> if so, check for compatibility and return (the first that is compatible)
678  bool ghostHit = false;
679  for (const TrueHitInfo& info : trueHitInfos) {
680  B2DEBUG(28, "Now checking trueHit: " << info);
681  if (nClusters == info.getNClusters()) {
682  TrueHitType* trueHit = trueHits[info.m_Id];
683  if (compatibleCombination(spacePoint, trueHit)) {
684  double weight = (detType == c_PXD ? 1 : calculateRelationWeight(info, spacePoint)); // if PXD weight is always 1!
685  return std::make_pair(trueHit, weight);
686  }
687  } else {
688  B2DEBUG(28, "The number of related Clusters ( = " << nClusters << ") and the number of associated weights ( = " <<
689  info.getNClusters() << ") do not match! This indicates a ghost hit");
690  ghostHit = true;
691  }
692  }
693  if (ghostHit) m_ghostHitCtr[m_iCont]++;
694 
695  // B2DEBUG(28, "just before return in getTHwithWeight")
696  return THwithWeight;
697 }
698 
699 // ============================================== CHECK IF SPACEPOINT AND TRUEHIT ARE COMPATIBLE ==================================
700 template <typename TrueHitType>
702 {
703  B2DEBUG(25, "Checking TrueHit " << trueHit->getArrayIndex() << " from Array " << trueHit->getArrayName() << " and SpacePoint " <<
704  spacePoint->getArrayIndex() << " from Array " << spacePoint->getArrayName() << " for compatibility");
705 
706  // check primary first
707  MCParticle* mcPart = trueHit->template getRelatedFrom<MCParticle>("ALL");
708  bool primaryPart = false; // assume secondary or background for safety
709  if (mcPart != nullptr) primaryPart = mcPart->hasStatus(MCParticle::c_PrimaryParticle);
710  if (m_PARAMrequirePrimary && !primaryPart) {
711  B2DEBUG(25, "TrueHit is not related to a primary particle but 'requirePrimary' is set to true!");
713  return false;
714  }
715 
716  // CAUTION: if further tests are added, make sure that they do not get 'over-ruled' by this one (i.e. put before this if)
718  B2DEBUG(29, "Not checking positions because 'requireProximity' is set to false");
719  return true;
720  }
721  const VxdID spacePointVxdId = spacePoint->getVxdID();
722  const VxdID trueHitVxdId = trueHit->getSensorID();
723 
724  B2DEBUG(29, "Comparing the VxdIDs, SpacePoint: " << spacePointVxdId << ", TrueHit: " << trueHitVxdId);
725  if (spacePointVxdId != trueHitVxdId) {
726  B2DEBUG(25, "SpacePoint and TrueHit do not have the same VxdID. spacePoint: " << spacePointVxdId << ", trueHit: " << trueHitVxdId);
727  return false;
728  }
729 
731  trueHitVxdId); // only have to get one, since VxdIds are already the same at this point!
732  double maxUres = SensorInfoBase.getUPitch(trueHit->getV()) / sqrt(12.) * m_PARAMmaxPosSigma;
733  double maxVres = SensorInfoBase.getVPitch(trueHit->getV()) / sqrt(12.) * m_PARAMmaxPosSigma;
734 
735  B2DEBUG(29, "maximum residual in U: " << maxUres << ", in V: " << maxVres);
736 
737  const ROOT::Math::XYZVector trueHitLocalPos = ROOT::Math::XYZVector(trueHit->getU(), trueHit->getV(), 0);
738  const ROOT::Math::XYZVector trueHitGlobalPos = SensorInfoBase.pointToGlobal(trueHitLocalPos, true); // uses alignment
739 
740  std::pair<double, double> spacePointLocal = getLocalPos(spacePoint);
741  // compare only those values of the local coordinates that have been set
742  std::pair<bool, bool> setCoordinates = spacePoint->getIfClustersAssigned();
743 
744  if (setCoordinates.first) {
745  B2DEBUG(29, "Comparing the U-coordinates, SpacePoint: " << spacePointLocal.first << ", TrueHit: " << trueHitLocalPos.X() <<
746  " -> diff: " << spacePointLocal.first - trueHitLocalPos.X());
747  if (pow(spacePointLocal.first - trueHitLocalPos.X(), 2) > maxUres * maxUres) {
748  B2DEBUG(25, "The local position difference in U direction is " << spacePointLocal.first - trueHitLocalPos.X() <<
749  " but maximum local position difference is set to: " << maxUres);
750  return false;
751  }
752  }
753  if (setCoordinates.second) {
754  B2DEBUG(29, "Comparing the V-coordinates, SpacePoint: " << spacePointLocal.second << ", TrueHit: " << trueHitLocalPos.Y() <<
755  " -> diff: " << spacePointLocal.second - trueHitLocalPos.Y());
756  if (pow(spacePointLocal.second - trueHitLocalPos.Y(), 2) > maxVres * maxVres) {
757  B2DEBUG(25, "The local position difference in V direction is " << spacePointLocal.second - trueHitLocalPos.Y() <<
758  " but maximum local position difference is set to: " << maxVres);
759  return false;
760  }
761  }
762 
763  // only if both local coordinates of a SpacePoint are set, compare also the global positions!
764  if (setCoordinates.first && setCoordinates.second) {
765  B2DEBUG(29, "Comparing the global positions, SpacePoint: (" << spacePoint->X() << "," << spacePoint->Y() << "," << spacePoint->Z()
766  << "), TrueHit: (" << trueHitGlobalPos.X() << "," << trueHitGlobalPos.Y() << "," << trueHitGlobalPos.Z() << ")");
767  if (pow(spacePoint->X() - trueHitGlobalPos.X(), 2) > m_maxGlobalDiff
768  || pow(spacePoint->Y() - trueHitGlobalPos.Y(), 2) > m_maxGlobalDiff ||
769  pow(spacePoint->Z() - trueHitGlobalPos.Z(), 2) > m_maxGlobalDiff) {
770  B2DEBUG(25, "The position differences are for X: " << spacePoint->X() - trueHitGlobalPos.X() << ", Y: " << spacePoint->Y() -
771  trueHitGlobalPos.Y() << " Z: " << spacePoint->Z() - trueHitGlobalPos.Z() << " but the maximum position difference is set to: " <<
773  return false;
774  }
775  } else {
776  B2DEBUG(20, "For SpacePoint " << spacePoint->getArrayIndex() <<
777  " one of the local coordinates was not assigned. The global positions and the un-assigned local coordinate were not compared!");
778  }
779 
780  return true;
781 }
782 
783 // ===================================================== GET LOCAL SPACEPOINT COORDINATES =========================================
785 {
786  // get the normalized local coordinates from SpacePoint and convert them to local coordinates (have to do so because at the slanted parts the local U-position is dependant on the local V-position)
787  // NOTE: second way is to convert the global position of the SpacePoint to local position via the sensorInfoBase (yields same results)
788  double normU = spacePoint->getNormalizedLocalU();
789  double normV = spacePoint->getNormalizedLocalV();
790  return spacePoint->convertNormalizedToLocalCoordinates(std::make_pair(normU, normV), spacePoint->getVxdID());
791 }
792 
793 // =============================================================== GET TRUEHIT POSITIONS ==========================================
794 template<typename TrueHitType>
795 std::pair<ROOT::Math::XYZVector, ROOT::Math::XYZVector> SpacePoint2TrueHitConnectorModule::getTrueHitPositions(TrueHitType* trueHit)
796 {
797 // TrueHitType* trueHit = trueHits[index];
798  const ROOT::Math::XYZVector localPos = ROOT::Math::XYZVector(trueHit->getU(), trueHit->getV(), 0);
799 
800  const VxdID trueHitVxdId = trueHit->getSensorID();
801  VXD::SensorInfoBase SensorInfoBase = VXD::GeoCache::getInstance().getSensorInfo(trueHitVxdId);
802  const ROOT::Math::XYZVector globalPos = SensorInfoBase.pointToGlobal(localPos, true); // uses alignment
803 
804  return std::make_pair(localPos, globalPos);
805 }
806 
807 // ================================================================= INITIALIZE ROOT FILE =========================================
809 {
810  if (m_PARAMrootFileName.size() != 2 || (m_PARAMrootFileName[1] != "UPDATE" && m_PARAMrootFileName[1] != "RECREATE")) {
811  std::string output;
812  for (std::string entry : m_PARAMrootFileName) {
813  output += "'" + entry + "' ";
814  }
815  B2FATAL("CurlingTrackCandSplitter::initialize() : rootFileName is set wrong: entries are: " << output);
816  }
817 
818  std::string fileName = m_PARAMrootFileName[0] + ".root";
819  m_rootFilePtr = new TFile(fileName.c_str(), m_PARAMrootFileName[1].c_str());
820  m_treePtr = new TTree("PosAnaTree", "Position Analysis");
821 
822  // link the variables
823  m_treePtr->Branch("SPLocalU", &m_rootVariables.SpacePointULocal);
824  m_treePtr->Branch("SPLocalV", &m_rootVariables.SpacePointVLocal);
825  m_treePtr->Branch("SPGlobalX", &m_rootVariables.SpacePointXGlobal);
826  m_treePtr->Branch("SPGlobalY", &m_rootVariables.SpacePointYGlobal);
827  m_treePtr->Branch("SPGlobalZ", &m_rootVariables.SpacePointZGlobal);
828 
829  m_treePtr->Branch("THLocalU", &m_rootVariables.TrueHitULocal);
830  m_treePtr->Branch("THLocalV", &m_rootVariables.TrueHitVLocal);
831  m_treePtr->Branch("THGlobalX", &m_rootVariables.TrueHitXGlobal);
832  m_treePtr->Branch("THGlobalY", &m_rootVariables.TrueHitYGlobal);
833  m_treePtr->Branch("THGlobalZ", &m_rootVariables.TrueHitZGlobal);
834 
835  m_treePtr->Branch("WeightU", &m_rootVariables.WeightU);
836  m_treePtr->Branch("WeightV", &m_rootVariables.WeightV);
837 
838  m_treePtr->Branch("relStatus", &m_rootVariables.RelationStatus);
839  m_treePtr->Branch("VxdID", &m_rootVariables.HitVxdID);
840  m_treePtr->Branch("nRelations", &m_rootVariables.NRelations);
841 
842  m_treePtr->Branch("clusterSizeU", &m_rootVariables.ClusterSizeU);
843  m_treePtr->Branch("clusterSizeV", &m_rootVariables.ClusterSizeV);
844  m_treePtr->Branch("SPErrorU", &m_rootVariables.SpacePointErrorU);
845  m_treePtr->Branch("SPErrorV", &m_rootVariables.SpacePointErrorV);
846  m_treePtr->Branch("SPErrorX", &m_rootVariables.SpacePointErrorX);
847  m_treePtr->Branch("SPErrorY", &m_rootVariables.SpacePointErrorY);
848  m_treePtr->Branch("SPErrorZ", &m_rootVariables.SpacePointErrorZ);
849 }
850 
851 // ========================================================= CLOSE ROOT FILE ======================================================
853 {
854  if (m_treePtr != nullptr && m_rootFilePtr != nullptr) {
855  m_rootFilePtr->cd(); //important! without this the famework root I/O (SimpleOutput etc) could mix with the root I/O of this module
856 // m_treePtr->Write(); // using TTree::Write() instead, which calls this any way
857  m_rootFilePtr->Write();
858  m_rootFilePtr->Close();
859  }
860 }
861 
862 // TODO TODO TODO TODO TODO TODO TODO: remove if not needed, only for tessting at the moment (i.e. do not commit)
863 std::pair<unsigned short int, unsigned short int> SpacePoint2TrueHitConnectorModule::getClusterSizes(Belle2::SpacePoint* spacePoint,
864  e_detTypes detType)
865 {
866  std::pair<unsigned short int, unsigned short int> clusterSizes = { 0, 0 };
867  if (detType == c_PXD) {
868  std::vector<std::pair<PXDCluster*, double> > relClusters = getRelatedClusters<PXDCluster>(spacePoint, m_PXDClusters.getName());
869  return std::make_pair(relClusters[0].first->getUSize(), relClusters[0].first->getVSize());
870  } else {
871  std::vector<std::pair<SVDCluster*, double> > relClusters = getRelatedClusters<SVDCluster>(spacePoint, m_SVDClusters.getName());
872  for (auto cluster : relClusters) {
873  if (cluster.first->isUCluster()) clusterSizes.first = cluster.first->getSize();
874  else clusterSizes.second = cluster.first->getSize();
875  }
876  }
877  return clusterSizes;
878 }
879 
881 {
882  auto detType = spacePoint->getType();
883  std::pair<double, double> errors = { -1., -1. };
884  if (detType == VXD::SensorInfoBase::PXD) {
885  std::vector<std::pair<PXDCluster*, double> > relClusters = getRelatedClusters<PXDCluster>(spacePoint, m_PXDClusters.getName());
886  errors.first = relClusters[0].first->getUSigma();
887  errors.second = relClusters[0].first->getVSigma();
888  } else if (detType == VXD::SensorInfoBase::SVD) {
889  std::vector<std::pair<SVDCluster*, double> > relClusters = getRelatedClusters<SVDCluster>(spacePoint, m_SVDClusters.getName());
890  for (auto cluster : relClusters) {
891  if (cluster.first->isUCluster()) { errors.first = cluster.first->getPositionSigma(); }
892  else { errors.second = cluster.first->getPositionSigma(); }
893  }
894  } else {
895  B2ERROR("Detector type not known in SpacePoint2TrueHitConnector::getLocalError() !");
896  }
897 
898  return errors;
899 }
900 // TODO TODO TODO TODO TODO TODO TODO: remove if not needed, only for tessting at the moment (i.e. do not commit)
901 
902 // ==================================================== CALCULATE RELATION WEIGHT ==================================================
904 {
905  bool isUAssigned = spacePoint->getIfClustersAssigned().first; // get if the Cluster in the SpacePoint is a U-Cluster
906  // get if two Clusters are related to the Truehit (always false for single Cluster SPs
907  bool bothClusters = trueHitInfo.m_U && trueHitInfo.m_V;
908  // calculate the additional weight that identifies which Clusters are related to this TrueHit
909  // 0 -> both Clusters have Relation to TrueHit, 10 -> only U-Cluster, 20 -> only V-Cluster has Relation to TrueHit
910  short addWeight = 20 - (bothClusters ? 20 : isUAssigned ? 10 : 0);
911 
912  return addWeight + (bothClusters ? 2 : 1);
913 }
DataType Z() const
access variable Z (= .at(2) without boundary check)
Definition: B2Vector3.h:435
DataType X() const
access variable X (= .at(0) without boundary check)
Definition: B2Vector3.h:431
DataType Y() const
access variable Y (= .at(1) without boundary check)
Definition: B2Vector3.h:433
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
Definition: DataStore.h:71
@ c_ErrorIfAlreadyRegistered
If the object/array was already registered, produce an error (aborting initialisation).
Definition: DataStore.h:72
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
Definition: DataStore.h:59
static Environment & Instance()
Static method to get a reference to the Environment instance.
Definition: Environment.cc:28
@ c_Debug
Debug: for code development.
Definition: LogConfig.h:26
static LogSystem & Instance()
Static method to get a reference to the LogSystem instance.
Definition: LogSystem.cc:31
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
bool hasStatus(unsigned short int bitmask) const
Return if specific status bit is set.
Definition: MCParticle.h:129
int getArrayIndex() const
Get 0-based index of the particle in the corresponding MCParticle list.
Definition: MCParticle.h:244
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:112
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
const std::string & getName() const
Returns the name of the module.
Definition: Module.h:187
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.
void addRelationTo(const RelationsInterface< BASE > *object, float weight=1.0, const std::string &namedRelation="") const
Add a relation from this object to another object (with caching).
std::string getArrayName() const
Get name of array this object is stored in, or "" if not found.
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.
FROM * getRelatedFrom(const std::string &name="", const std::string &namedRelation="") const
Get the object from which this object has a relation.
std::vector< std::string > m_PARAMclusterNames
names of containers of Clusters
std::pair< TrueHitType *, double > getTHwithWeight(const MapType &aMap, Belle2::StoreArray< TrueHitType > trueHits, Belle2::SpacePoint *spacePoint, e_detTypes detType)
get the TrueHit from information that is stored in the map (conditions are checked in the following o...
std::vector< std::string > m_PARAMtrueHitNames
names of containers of TrueHits
std::vector< unsigned int > m_SpacePointsCtr
Number of SpacePoints presented to the module.
std::vector< std::string > m_PARAMdetectorTypes
detector type names as strings to determine which name belongs to which detector type
void initialize() override
initialize: initialize counters, check StoreArrays, register StoreArrays, ...
unsigned int m_nContainers
number of passed containers -> storing the size of an input vector for not having to obtain it every ...
void reRegisterClusterRelations(Belle2::SpacePoint *origSpacePoint, Belle2::SpacePoint *newSpacePoint, std::string clusterName="ALL")
register all the relations to Clusters that origSpacePoint had for newSpacePoint
RootVariables m_rootVariables
Root variables used for collecting data eventwise.
std::vector< unsigned int > m_rejectedRelsCtr
Number of SpacePoints that were not related to a TrueHit (i.e.
void event() override
event: try to find the appropriate TrueHit to all SpacePoints
MapType getRelatedTrueHits(Belle2::SpacePoint *spacePoint, std::string clusterName="ALL", std::string trueHitName="ALL")
get all the related TrueHits to the SpacePoint, including their weights in a map (multimap!...
std::pair< double, double > getLocalError(Belle2::SpacePoint *spacePoint)
get the position error of SpacePoints in local coordinates
void registerAllRelations(Belle2::SpacePoint *spacePoint, MapType trueHitMap, e_detTypes detType)
register a Relation to all the TrueHits in the trueHitMap for the passed SpacePoint
std::vector< unsigned int > m_noClusterCtr
Number of SpacePoints without relation to a Cluster (i.e.
std::vector< std::pair< Belle2::StoreArray< Belle2::SpacePoint >, e_detTypes > > m_inputSpacePoints
StoreArray of all input SpacePoints.
double m_PARAMmaxGlobalDiff
maximum difference of global position coordinates for each direction between TrueHit and SpacePoint
void initializeRootFile()
initialize the root file that is used for output
std::unordered_map< int, TrueHitInfo > baseMapT
typedef for shorter notation throughout the module
std::vector< unsigned int > m_regRelationsCtr
Number of registered relations.
unsigned int m_weightTooSmallCtr
Count the omitted relations because of a too small weight.
void terminate() override
terminate: print some summary information
unsigned int m_iCont
'helper variable' needed to not have to pass one integer down to processSpacePoint only to have a han...
std::vector< std::pair< ClusterType *, double > > getRelatedClusters(Belle2::SpacePoint *spacePoint, std::string clusterName="ALL")
get the pointers to the related Clusters and the weight of the original Relations between the spacePo...
std::vector< std::array< unsigned int, 5 > > m_nRelTrueHitsCtr
counting different numbers of related TrueHits (to a SpacePoint) with one variable
void positionAnalysis(Belle2::SpacePoint *spacePoint, const MapType &trueHitMap, const int &index, e_detTypes detType)
Analyze the position of SpacePoints and corresponding TrueHits.
bool m_PARAMstoreSeparate
switch for storing the SpacePoints that can be related to a TrueHit into separate StoreArrays,...
unsigned int m_rejectedNoPrimaryCtr
Count how many times a relation was rejected because TrueHit was not related to primary.
std::vector< Belle2::StoreArray< Belle2::SpacePoint > > m_outputSpacePoints
StoreArray of all output SpacePoints.
std::pair< unsigned short int, unsigned short int > getClusterSizes(Belle2::SpacePoint *spacePoint, e_detTypes detType)
get the sizes of the related Clusters of a SpacePoint
MapType processSpacePoint(Belle2::SpacePoint *spacePoint, e_detTypes detType)
process a SpacePoint.
std::vector< e_detTypes > m_detectorTypes
storing the detector types for each container in vector, needed in initialize
std::vector< std::string > m_PARAMrootFileName
name and update status of root file
double m_maxGlobalDiff
storing the squared value of m_PARAMmaxGlobalDiff here to not alter the parameter input
void registerTrueHitRelation(Belle2::SpacePoint *spacePoint, int index, double weight, Belle2::StoreArray< TrueHitType > trueHits)
register the relation between a SpacePoint and the TrueHit (passed by index in the correspoinding Tru...
std::vector< unsigned int > m_noTrueHitCtr
Number of SpacePoints that contained a Cluster to which no TrueHit could be found (i....
std::string m_PARAMoutputSuffix
suffix that will be appended to the StoreArray names of the output StoreArrays
Belle2::StoreArray< Belle2::SVDTrueHit > m_SVDTrueHits
SVDTrueHits StoreArray used throughout the module.
bool m_PARAMrequirePrimary
require the TrueHit to be related to a primary particle in order for the relation to get registered!
double m_PARAMmaxPosSigma
defining th maximum difference of local coordinates in units of PitchSize / sqrt(12)
Belle2::StoreArray< Belle2::PXDTrueHit > m_PXDTrueHits
PXDTrueHits StoreArray used throughout the module.
Belle2::StoreArray< Belle2::PXDCluster > m_PXDClusters
PXDTClusters StoreArray used throughout the module.
bool m_PARAMregisterAll
switch for registereing all relations for all TrueHits for all SpacePoints (there can be more than 1 ...
Belle2::StoreArray< Belle2::SVDCluster > m_SVDClusters
PXDClusters StoreArray used throughout the module.
void registerOneRelation(Belle2::SpacePoint *spacePoint, std::pair< TrueHitType *, double > trueHitwWeight, e_detTypes)
register Relation between SpacePoint and TrueHit (and if neccessary also between SpacePoint and Clust...
double calculateRelationWeight(const TrueHitInfo &trueHitInfo, Belle2::SpacePoint *spacePoint)
calculate the Relation weight to be used (for SVD only, although method works with PXD as well!...
std::pair< ROOT::Math::XYZVector, ROOT::Math::XYZVector > getTrueHitPositions(TrueHitType *trueHit)
get the local (.first) and global (.second) position of a TrueHit (passed by index)
bool m_PARAMrequireProximity
require the TrueHit to be close to the SpacePoint.
std::vector< std::string > m_PARAMspacePointNames
names of containers of SpacePoints
std::pair< double, double > getLocalPos(Belle2::SpacePoint *spacePoint)
get the local position of a SpacePoint
void initializeCounters()
initialize all counters to 0 WARNING: only call in constructor of module!
bool compatibleCombination(Belle2::SpacePoint *spacePoint, TrueHitType *trueHit)
compares the TrueHit and the SpacePoint positions (global) to decide whether they are compatible NOTE...
bool m_PARAMpositionAnalysis
switch for doing the analysis of positions of SpacePoints and TrueHits
double m_PARAMminWeight
define a minimal weight a relation between Cluster and TrueHit.
std::vector< unsigned int > m_ghostHitCtr
Number of SpacePoints that are considered ghost hits.
SpacePoint typically is build from 1 PXDCluster or 1-2 SVDClusters.
Definition: SpacePoint.h:42
unsigned short getNClustersAssigned() const
Returns the number of Clusters assigned to this SpacePoint.
Definition: SpacePoint.h:165
double getNormalizedLocalV() const
Return normalized local coordinates of the cluster in v (0 <= posV <= 1).
Definition: SpacePoint.h:154
VxdID getVxdID() const
Return the VxdID of the sensor on which the the cluster of the SpacePoint lives.
Definition: SpacePoint.h:148
const B2Vector3< double > & getPositionError() const
return the hitErrors in sigma of the global position
Definition: SpacePoint.h:141
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
static std::pair< double, double > convertNormalizedToLocalCoordinates(const std::pair< double, double > &hitNormalized, Belle2::VxdID vxdID, const Belle2::VXD::SensorInfoBase *aSensorInfo=nullptr)
converts a hit in sensor-independent relative coordinates into local coordinate of given sensor.
Definition: SpacePoint.cc:178
double Z() const
return the z-value of the global position of the SpacePoint
Definition: SpacePoint.h:129
double X() const
return the x-value of the global position of the SpacePoint
Definition: SpacePoint.h:123
double getNormalizedLocalU() const
Return normalized local coordinates of the cluster in u (0 <= posU <= 1).
Definition: SpacePoint.h:151
double Y() const
return the y-value of the global position of the SpacePoint
Definition: SpacePoint.h:126
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
const std::string & getName() const
Return name under which the object is saved in the DataStore.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
Class VXDTrueHit - Records of tracks that either enter or leave the sensitive volume.
Definition: VXDTrueHit.h:36
const SensorInfoBase & getSensorInfo(Belle2::VxdID id) const
Return a referecne to the SensorInfo of a given SensorID.
Definition: GeoCache.cc:67
static GeoCache & getInstance()
Return a reference to the singleton instance.
Definition: GeoCache.cc:214
Base class to provide Sensor Information for PXD and SVD.
double getUPitch(double v=0) const
Return the pitch of the sensor.
ROOT::Math::XYZVector pointToGlobal(const ROOT::Math::XYZVector &local, bool reco=false) const
Convert a point from local to global coordinates.
double getVPitch(double v=0) const
Return the pitch of the sensor.
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33
helper class for setting up a bitfield that can be used to store several flags in one variable TODO: ...
void setStatus(T __statusBits)
set the status of the bitfield (CAUTION: overwrites any previously defined status!...
void addStatus(T __statusBits)
add a status to the bitfield (if it has not already been added)
const T getStatus() const
get the status of the bitfield
REG_MODULE(arichBtest)
Register the Module.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
std::vector< typename MapType::key_type > getUniqueKeys(const MapType &aMap)
get the unique keys of a map (i.e.
std::string printMap(const MapType &aMap)
get the contents of the map as string.
unsigned int getUniqueSize(const MapType &aMap)
get the number of unique keys inside the map NOTE: for non-multimap this is the same as ....
std::vector< typename MapType::mapped_type > getAllValues(const MapType &aMap)
get all values in the map (i.e.
Abstract base class for different kinds of events.
helper struct to access root variables inside the module
std::vector< unsigned int > ClusterSizeV
size of the v-cluster (resp.
std::vector< double > WeightV
weight of the relation between the V-Cluster of the SpacePoint and the TrueHit
std::vector< double > SpacePointErrorZ
positiion error of SpacePoint in Z direction (global)
std::vector< double > TrueHitXGlobal
TrueHit global X-position.
std::vector< double > SpacePointErrorX
positiion error of SpacePoint in X direction (global)
std::vector< double > SpacePointVLocal
SpacePoint local V-position.
std::vector< unsigned int > ClusterSizeU
size of the u-cluster (resp.
std::vector< double > SpacePointErrorY
positiion error of SpacePoint in Y direction (global)
std::vector< unsigned int > NRelations
Number of related TrueHits to a SpacePoint.
std::vector< double > SpacePointXGlobal
SpacePoint global X-position.
std::vector< unsigned short int > HitVxdID
VxdID of the SpacePoint/TrueHit.
std::vector< double > SpacePointErrorU
position error of SpacePoint in U direction
std::vector< unsigned short int > RelationStatus
different flags of the relation stored in here (see c_relationStatus)
std::vector< double > SpacePointYGlobal
SpacePoint global Y-position.
std::vector< double > SpacePointULocal
SpacePoint local U-position.
std::vector< double > SpacePointZGlobal
SpacePoint global Z-position.
std::vector< double > TrueHitYGlobal
TrueHit global Y-position.
std::vector< double > SpacePointErrorV
position error of SpacePoint in V direction
std::vector< double > WeightU
weight of the relation between the U-Cluster of the SpacePoint and the TrueHit
std::vector< double > TrueHitZGlobal
TrueHit global Z-position.
helper struct that holds information that is needed for the registration of the relation between Spac...
bool m_U
if true, U-Cluster is used by SpacePoint
bool m_V
if true, V-Cluster is used by SpacePoint