Belle II Software development
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
30using namespace Belle2;
31
32
33REG_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 accessible 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 separate 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 omitted! 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 " <<
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
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
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)!");
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 << "Omitted 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 ======================================================
305template<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());
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
329template<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 ===================================================
425template<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 ==========================================================
453template<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 is 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 =========================================
475template<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 ===============================================
491template<typename ClusterType>
492std::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 ==============================================
509template<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
522template<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());
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 ======================================================
625template<typename MapType, typename TrueHitType>
626std::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 ==================================
700template <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 dependent 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 ==========================================
794template<typename TrueHitType>
795std::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)
863std::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
const std::string & getName() const
Returns the name of the module.
Definition: Module.h:187
@ 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
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.
FROM * getRelatedFrom(const std::string &name="", const std::string &namedRelation="") const
Get the object from which this object has a relation.
RelationVector< TO > getRelationsTo(const std::string &name="", const std::string &namedRelation="") const
Get the relations that point from this object to another store array.
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 corresponding True...
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 necessary also between SpacePoint and Cluste...
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
std::pair< bool, bool > getIfClustersAssigned() const
Returns, if u(v)-coordinate is based on cluster information.
Definition: SpacePoint.h:162
VxdID getVxdID() const
Return the VxdID of the sensor on which the the cluster of the SpacePoint lives.
Definition: SpacePoint.h:148
const B2Vector3D & getPositionError() const
return the hitErrors in sigma of the global position
Definition: SpacePoint.h:141
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
const std::string & getName() const
Return name under which the object is saved in the DataStore.
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
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
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
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
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.
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.
std::string printMap(const MapType &aMap)
get the contents of the map as string.
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