ATLAS Offline Software
Loading...
Searching...
No Matches
SCT_ClusteringTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
10
25
28
30
31#include <algorithm>
32#include <cmath>
33
34namespace InDet {
35
36 // Functor to enable sorting of RDOs by first strip
38 public:
39 bool operator()(const SCT_RDORawData* rdo1, const SCT_RDORawData* rdo2) {
40 return rdo1->identify() < rdo2->identify();
41 }
42 };
43
44 // Are two strips adjacent?
45 bool adjacent(unsigned int strip1, unsigned int strip2) {
46 return ((1 == (strip2-strip1)) or (1 == (strip1-strip2)));
47 }
48
49 //version for when using rows
50 bool adjacent(const unsigned int strip1, const int row1, const unsigned int strip2, const int row2){
51 return ((row1==row2) and ((1 == (strip2-strip1)) or (1 == (strip1-strip2))));
52 }
53
54 // Constructor with parameters:
55 SCT_ClusteringTool::SCT_ClusteringTool(const std::string& type, const std::string& name, const IInterface* parent) :
56 base_class(type, name, parent)
57 {
58 }
59
61 // Decode time bins from string of form e.g. "01X" to integer bits (-1 means X)
62 m_timeBinBits[0] = -1;
63 m_timeBinBits[1] = -1;
64 m_timeBinBits[2] = -1;
65
66 if (m_timeBinStr.empty()) return StatusCode::SUCCESS;
67 if (m_timeBinStr.size() != 3) {
68 ATH_MSG_FATAL("Time bin string must only contain 3 bins");
69 return StatusCode::FAILURE;
70 }
71 std::transform(m_timeBinStr.begin(), m_timeBinStr.end(), m_timeBinStr.begin(), ::toupper);
72
73 for (unsigned int i(0); i<m_timeBinStr.size(); ++i) {
74 int timeBin(-999);
75 if (decodeTimeBin(m_timeBinStr[i], timeBin).isFailure()) return StatusCode::FAILURE;
76 m_timeBinBits[i] = timeBin;
77 }
78
79 return StatusCode::SUCCESS;
80 }
81
82 StatusCode SCT_ClusteringTool::decodeTimeBin(char timeBin, int& bit) const {
83 // Decode individual time char
84 if (timeBin == 'X') {bit = -1; return StatusCode::SUCCESS;}
85 if (timeBin == '0') {bit = 0; return StatusCode::SUCCESS;}
86 if (timeBin == '1') {bit = 1; return StatusCode::SUCCESS;}
87
88 ATH_MSG_FATAL("Invalid time bin string " << timeBin);
89 return StatusCode::FAILURE;
90 }
91
92 bool SCT_ClusteringTool::testTimeBins(int timeBin) const {
93 // Convert the given timebin to a bit set and test each bit
94 // if bit is -1 (i.e. X) it always passes, other wise require exact match of 0/1
95 // N.B bitset has opposite order to the bit pattern we define
96
97 const std::bitset<3> timePattern(static_cast<unsigned long>(timeBin));
98 return testTimeBinsN(timePattern);
99 }
100
102 // Convert the given timebin to a bit set and test each bit
103 // if bit is -1 (i.e. X) it always passes, otherwise require exact match of 0/1
104 // N.B bitset has opposite order to the bit pattern we define
105
106 bool pass(true);
107 const std::bitset<3> timePattern(static_cast<unsigned long>(timeBin));
108 if (timePattern.test(2)) pass=false;
109 if (!timePattern.test(1)) pass=false;
110 return pass;
111 }
112
114 // Convert the given timebin to a bit set and test each bit
115 // if bit is -1 (i.e. X) it always passes, otherwise require exact match of 0/1
116 // N.B bitset has opposite order to the bit pattern we define
117
118 bool pass(true);
119 const std::bitset<3> timePattern(static_cast<unsigned long>(timeBin));
120 if (!timePattern.test(1)) pass=false;
121 return pass;
122 }
123
125 ATH_CHECK(m_clusterMaker.retrieve());
126
127 if (m_checkBadChannels && m_sctDetElStatus.empty()) {
128 ATH_MSG_DEBUG("Clustering has been asked to look at bad channel info");
129 ATH_CHECK(m_conditionsTool.retrieve());
130 } else {
131 m_conditionsTool.disable();
132 }
133
134 if (m_doFastClustering and not m_lorentzAngleTool.empty()) {
135 ATH_CHECK(m_lorentzAngleTool.retrieve());
136 } else {
137 m_lorentzAngleTool.disable();
138 }
139
140 if (decodeTimeBins().isFailure()) return StatusCode::FAILURE;
141
145 int countTrueSettings(0);
146 if (m_majority01X) countTrueSettings++;
147 if (m_innermostBarrelX1X) countTrueSettings++;
148 if (m_innertwoBarrelX1X) countTrueSettings++;
149 if (countTrueSettings!=1) {
150 if (!m_timeBinStr.empty()) {
151 ATH_MSG_DEBUG("Timing requirement: m_timeBinStr " << m_timeBinStr << " is used for clustering");
152 } else {
153 if (countTrueSettings==0) {
154 ATH_MSG_DEBUG("Timing requirement is not used for clustering");
155 } else {
156 ATH_MSG_FATAL("One and only one of m_majority01X, m_innermostBarrelX1X and m_innertwoBarrelX1X should be set to True!");
157 return StatusCode::FAILURE;
158 }
159 }
160 } else {
161 ATH_MSG_DEBUG("Timing requirement: " <<
162 (m_majority01X ? "m_majority01X" : "") <<
163 (m_innermostBarrelX1X ? "m_innermostBarrelX1X" : "") <<
164 (m_innertwoBarrelX1X ? "m_innertwoBarrelX1X" : "") <<
165 " is true and used for clustering");
166 }
167
168 ATH_CHECK(m_SCTDetEleCollKey.initialize());
169 ATH_CHECK(m_sctDetElStatus.initialize( !m_sctDetElStatus.empty()) );
170
171 return StatusCode::SUCCESS;
172 }
173
174 void SCT_ClusteringTool::addStripsToCluster(const Identifier& firstStripId, unsigned int nStrips,
175 std::vector<Identifier>& clusterVector, const SCT_ID& idHelper) {
176 const unsigned int firstStripNumber(idHelper.strip(firstStripId));
177 const unsigned int endStripNumber(firstStripNumber + nStrips); // one-past-the-end
178 const Identifier waferId(idHelper.wafer_id(firstStripId));
179 clusterVector.reserve(clusterVector.size() + nStrips);
180
181 for (unsigned int stripNumber(firstStripNumber); stripNumber not_eq endStripNumber; ++stripNumber) {
182 const Identifier stripId(idHelper.strip_id(waferId, stripNumber));
183 clusterVector.push_back(stripId);
184 }
185 }
186
193 unsigned int nStrips,
194 std::vector<Identifier>& clusterVector,
195 std::vector<std::vector<Identifier> >& idGroups,
196 const SCT_ID& idHelper,
197 const InDet::SiDetectorElementStatus *det_el_status,
198 const EventContext& ctx) const{
199
200 const unsigned int firstStripNumber(idHelper.strip(firstStripId));
201 const unsigned int endStripNumber(firstStripNumber + nStrips); // one-past-the-end
202 const Identifier waferId(idHelper.wafer_id(firstStripId));
203 IdentifierHash waferHash( idHelper.wafer_hash(waferId) );
204
205 clusterVector.reserve(clusterVector.size() + nStrips);
206
207 static const Identifier badId;
208 unsigned int nBadStrips(0);
209 for (unsigned int stripNumber(firstStripNumber); stripNumber not_eq endStripNumber; ++stripNumber) {
210 Identifier stripId(idHelper.strip_id(waferId, stripNumber));
211 if (isBad(det_el_status, idHelper, waferHash, stripId, ctx)) {
212 ++nBadStrips;
213 stripId = badId;
214 }
215 clusterVector.push_back(stripId);
216 }
217
218 // Maybe all the strips are bad, clear the cluster vector
219 if (clusterVector.size() == nBadStrips) {
220 clusterVector.clear();
221 // No need to recluster if vector is empty (same true if empty for other reasons)
222 return;
223 }
224
225 // Now we have one vector of stripIds, some of which may be 'bad'
226 if (nBadStrips != 0) {
227
228 clusterVector=recluster(clusterVector, idGroups);
229 // After this, the cluster vector is either empty or has the last good cluster
230 }
231 }
232
234 unsigned int nStrips,
235 std::vector<Identifier>& clusterVector,
236 std::vector<std::vector<Identifier> >& idGroups,
237 const SCT_ID& idHelper,
238 const InDet::SiDetectorElementStatus *det_el_status,
239 const EventContext& ctx) const{
240
241 const unsigned int firstStripNumber(idHelper.strip(firstStripId));
242 const unsigned int firstRowNumber(idHelper.row(firstStripId));
243 const unsigned int endStripNumber(firstStripNumber + nStrips); // one-past-the-end
244 const Identifier waferId(idHelper.wafer_id(firstStripId));
245 IdentifierHash waferHash( idHelper.wafer_hash(waferId) );
246
247 clusterVector.reserve(clusterVector.size() + nStrips);
248 static const Identifier badId;
249 unsigned int nBadStrips(0);
250 for (unsigned int stripNumber(firstStripNumber); stripNumber not_eq endStripNumber; ++stripNumber) {
251 Identifier stripId(idHelper.strip_id(waferId, firstRowNumber, stripNumber));
252 if (isBad(det_el_status, idHelper, waferHash, stripId, ctx)) {
253 ++nBadStrips;
254 stripId = badId;
255 }
256 clusterVector.push_back(stripId);
257 }
258
259 // Maybe all the strips are bad, clear the cluster vector
260 if (clusterVector.size() == nBadStrips) {
261 clusterVector.clear();
262 // No need to recluster if vector is empty (same true if empty for other reasons)
263 return;
264 }
265
266 // Now we have one vector of stripIds, some of which may be 'bad'
267 if (nBadStrips != 0) {
268 clusterVector=recluster(clusterVector, idGroups);
269 // After this, the cluster vector is either empty or has the last good cluster
270 }
271 }
272
273
280 std::vector<SCT_ClusteringTool::IdVec_t>& idGroups) const {
281
282 // Default Identifier constructor gives a sentinel value
283 static const Identifier invalidId;
284 const unsigned int numberOfBadStrips(std::count(clusterVector.begin(), clusterVector.end(), invalidId));
285
286 // All the strips are good, return the original vector to be put in idGroups by the caller
287 if (numberOfBadStrips==0 or clusterVector.empty()) return clusterVector;
288 // All the strips are bad, clear the vector and return it
289 if (clusterVector.size() == numberOfBadStrips) {
290 clusterVector.clear();
291 return clusterVector;
292 }
293
294 // Pointer to first bad strip
295 SCT_ClusteringTool::IdVec_t::iterator pBadId(std::find(clusterVector.begin(), clusterVector.end(), invalidId));
296 // Make a new cluster, which could be empty, if the first strip is bad
297 SCT_ClusteringTool::IdVec_t subCluster(clusterVector.begin(), pBadId);
298 // Remove elements including the badId
299 if (pBadId != clusterVector.end()) clusterVector.erase(clusterVector.begin(), ++pBadId);
300 if (not subCluster.empty()) idGroups.push_back(subCluster);
301 return recluster(clusterVector, idGroups);
302 }
303
304
307 const SCT_ID& idHelper,
308 const InDet::SiDetectorElementStatus *sctDetElStatus,
309 SCTClusteringCache& cache,
310 DataPool<SCT_Cluster>* dataItemsPool,
311 const EventContext& ctx) const
312 {
313 ATH_MSG_VERBOSE ("SCT_ClusteringTool::clusterize()");
314
315 if (m_doFastClustering) return fastClusterize(collection, idHelper, sctDetElStatus, cache, dataItemsPool, ctx);
316
317 SCT_ClusterCollection* nullResult(nullptr);
318 if (collection.empty()) {
319 ATH_MSG_DEBUG("Empty RDO collection");
320 return nullResult;
321 }
322
323 // Make a copy of the collection for sorting (no need to sort if theres only one RDO)
324 std::vector<const SCT_RDORawData*> collectionCopy(collection.begin(), collection.end());
325 if (collection.size() not_eq 1) std::sort(collectionCopy.begin(), collectionCopy.end(), strip_less_than());
326
327 // Vector of identifiers in a cluster (most likely is that there is one strip in the cluster)
328 // Vector of clusters to make the cluster collection (most likely equal to collection size)
329 cache.currentVector.clear();
330 cache.idGroups.clear();
331 cache.tbinGroups.clear();
332 int n01X(0);
333 int n11X(0);
334 unsigned int previousStrip(0); // Should be ok?
335 uint16_t hitsInThirdTimeBin(0);
336 int stripCount(0);
337 for (const SCT_RDORawData* pRawData: collectionCopy) {
338 const Identifier firstStripId(pRawData->identify());
339 const unsigned int nStrips(pRawData->getGroupSize());
340 const int thisStrip(idHelper.strip(firstStripId));
341 const int BEC(idHelper.barrel_ec(firstStripId));
342 const int layer(idHelper.layer_disk(firstStripId));
343
344 // Flushes the vector every time a non-adjacent strip is found
345 if (not adjacent(thisStrip, previousStrip) and not(cache.currentVector.empty())) {
346 if (m_majority01X) {
347 if (n01X >= n11X) {
348 cache.idGroups.push_back(cache.currentVector);
349 }
350 } else {
351 // Add this group to existing groups (and flush)
352 cache.idGroups.push_back(cache.currentVector);
353 }
354 cache.currentVector.clear();
355 n01X=0;
356 n11X=0;
357 cache.tbinGroups.push_back(hitsInThirdTimeBin);
358 hitsInThirdTimeBin =0;
359 stripCount = 0;
360 }
361
362 // Only use clusters with certain time bit patterns if m_timeBinStr set
363 bool passTiming(true);
364 bool pass01X(true);
365 bool passX1X(true);
366 const SCT3_RawData* pRawData3(dynamic_cast<const SCT3_RawData*>(pRawData));
367 if (!pRawData3) {
368 ATH_MSG_ERROR("Casting into SCT3_RawData failed. This is probably caused by use of an old RDO file.");
369 return nullptr;
370 }
371 const int timeBin(pRawData3->getTimeBin());
372 std::bitset<3> timePattern(static_cast<unsigned long>(timeBin));
373 if (not m_timeBinStr.empty()) passTiming = testTimeBins(timeBin);
374
375 passX1X = testTimeBinsX1X(pRawData3->getTimeBin());
376 if (passX1X) pass01X = testTimeBins01X(pRawData3->getTimeBin());
377 if (pass01X) n01X++;
378 if (passX1X and (not pass01X)) n11X++;
380 if ((BEC==0) and (layer==0) and passX1X) passTiming=true;
381 else passTiming = pass01X;
382 } else if (m_innertwoBarrelX1X) {
383 if ((BEC==0) and (layer==0 or layer==1) and passX1X) passTiming=true;
384 else passTiming = pass01X;
385 }
386
387 // Now we are either (a) pushing more contiguous strips onto an existing vector
388 // or (b) pushing a new set of ids onto an empty vector
389 if (passTiming or m_majority01X) {
391 addStripsToClusterInclRows(firstStripId, nStrips, cache.currentVector, cache.idGroups, idHelper,sctDetElStatus, ctx); // Note this takes the current vector only
392 } else if (not m_checkBadChannels) {
393 addStripsToCluster(firstStripId, nStrips, cache.currentVector, idHelper); // Note this takes the current vector only
394 } else {
395 addStripsToClusterWithChecks(firstStripId, nStrips, cache.currentVector, cache.idGroups, idHelper,sctDetElStatus, ctx); // This one includes the groups of vectors as well
396 }
397 for (unsigned int iStrip=0; iStrip<nStrips; iStrip++) {
398 if (stripCount < 16) hitsInThirdTimeBin |= (timePattern.test(0) << stripCount);
399 stripCount++;
400 }
401 }
402 if (not cache.currentVector.empty()) {
403 // Gives the last strip number in the cluster
404 previousStrip = idHelper.strip(cache.currentVector.back());
405 }
406 }
407
408 // Still need to add this last vector
409 if (not cache.currentVector.empty()) {
410 if ((not m_majority01X) or (n01X >= n11X)) {
411 cache.idGroups.push_back(cache.currentVector);
412 cache.tbinGroups.push_back(hitsInThirdTimeBin);
413 hitsInThirdTimeBin=0;
414 }
415 }
416
417 // Find detector element for these digits
418 const Identifier elementID(collection.identify());
419 const Identifier waferId{idHelper.wafer_id(elementID)};
420 const IdentifierHash waferHash{idHelper.wafer_hash(waferId)};
422 const InDetDD::SiDetectorElementCollection* sctDetEle(*sctDetEleHandle);
423 if (not sctDetEleHandle.isValid() or sctDetEle==nullptr) {
424 ATH_MSG_FATAL(m_SCTDetEleCollKey.fullKey() << " is not available.");
425 return nullResult;
426 }
427 const InDetDD::SiDetectorElement* element(sctDetEle->getDetectorElement(waferHash));
428 if (!element) {
429 ATH_MSG_WARNING("Element not in the element map, ID = "<< elementID);
430 return nullResult;
431 }
432
433 const InDetDD::SCT_ModuleSideDesign* design;
434 if (idHelper.is_barrel(elementID)) {
435 design = (static_cast<const InDetDD::SCT_BarrelModuleSideDesign*>(&element->design()));
436 } else {
437 design = (static_cast<const InDetDD::SCT_ForwardModuleSideDesign*>(&element->design()));
438 }
439
440 IdentifierHash idHash(collection.identifyHash());
441 SCT_ClusterCollection* clusterCollection = new SCT_ClusterCollection(idHash);
442 clusterCollection->setIdentifier(elementID);
443 clusterCollection->reserve(cache.idGroups.size());
444 //DataPool will own the elements
445 if(dataItemsPool){
446 clusterCollection->clear(SG::VIEW_ELEMENTS);
447 }
448
449 // All strips are assumed to be the same width.
450 std::vector<uint16_t>::iterator tbinIter(cache.tbinGroups.begin());
451
455 const bool badStripInClusterOnThisModuleSide = (cache.idGroups.size() != cache.tbinGroups.size());
456
457 for (IdVec_t& stripGroup: cache.idGroups) {
458 const int nStrips(stripGroup.size());
459 if (nStrips == 0) continue;
460 //
461 const InDetDD::SiLocalPosition dummyPos(1, 0);
462 DimensionAndPosition clusterDim(dummyPos, 1.0);//just initialize with arbitrary values, will be set properly in the next two lines...
463 if (m_useRowInformation) clusterDim = clusterDimensionsInclRow(idHelper.strip(stripGroup.front()), idHelper.strip(stripGroup.back()), idHelper.row(stripGroup.front()), element, design);
464 else clusterDim = clusterDimensions(idHelper.strip(stripGroup.front()), idHelper.strip(stripGroup.back()), element, idHelper);
465 const Amg::Vector2D localPos(clusterDim.centre.xPhi(), clusterDim.centre.xEta());
466 // Since clusterId is arbitary (it only needs to be unique) just use ID of first strip
467 //const Identifier clusterId = element->identifierOfPosition(clusterDim.centre);
468 const Identifier clusterId(stripGroup.front());
469 if (!clusterId.is_valid()) ATH_MSG_VERBOSE(clusterId << " is invalid.");
470 //
471 // Find length of strip at centre
472 const std::pair<InDetDD::SiLocalPosition, InDetDD::SiLocalPosition> ends(design->endsOfStrip(clusterDim.centre));
473 const double stripLength(std::abs(ends.first.xEta()-ends.second.xEta()));
474 //
475 // Now make a SiCluster
476 const SiWidth siWidth(Amg::Vector2D(nStrips, 1), Amg::Vector2D(clusterDim.width, stripLength));
477
478 SCT_Cluster* cluster = nullptr;
479 if (dataItemsPool){
480 cluster = dataItemsPool->nextElementPtr();
481 }else{
482 cluster = new SCT_Cluster();
483 }
484
485 (*cluster) =
487 ? (m_clusterMaker->sctCluster(clusterId, localPos, std::move(stripGroup),
488 siWidth, element, m_errorStrategy))
489 : (SCT_Cluster(clusterId, localPos, std::move(stripGroup), siWidth, element,
490 {}));
491
492 cluster->setHashAndIndex(clusterCollection->identifyHash(),
493 clusterCollection->size());
494 if (tbinIter != cache.tbinGroups.end()) {
495 cluster->setHitsInThirdTimeBin(*tbinIter);
496 ++tbinIter;
497 }
499 if (badStripInClusterOnThisModuleSide) cluster->setHitsInThirdTimeBin(0);
500 clusterCollection->push_back(cluster);
501 }
502
503 return clusterCollection;
504 }
505
507 const SCT_ID& idHelper,
508 const InDet::SiDetectorElementStatus *sctDetElStatus,
509 SCTClusteringCache& cache,
510 DataPool<SCT_Cluster>* dataItemsPool,
511 const EventContext& ctx) const
512 {
513 if (collection.empty()) return nullptr;
514
515 std::vector<const SCT_RDORawData*> collectionCopy(collection.begin(), collection.end());
516
517 if (collectionCopy.size() > 1) std::sort(collectionCopy.begin(), collectionCopy.end(), strip_less_than());
518
519 cache.currentVector.clear();
520 cache.idGroups.clear();
521 cache.tbinGroups.clear();
522
523 unsigned int previousStrip = 0; // Should be ok?
524 uint16_t hitsInThirdTimeBin = 0;
525 int stripCount = 0;
526 int previousRow = -1;
527 int thisRow = -1;
528
529 const Identifier badId;
530
531 for (const SCT_RDORawData* pRawData: collectionCopy) {
532 Identifier firstStripId = pRawData->identify();
533 Identifier waferId = idHelper.wafer_id(firstStripId);
534 IdentifierHash waferHash = idHelper.wafer_hash(waferId);
535 unsigned int nStrips = pRawData->getGroupSize();
536 int thisStrip = idHelper.strip(firstStripId);
537
538 if (m_useRowInformation) thisRow = idHelper.row(firstStripId);
539
540 // Flushes the vector every time a non-adjacent strip is found
541 //
542 if (not cache.currentVector.empty() and
543 ((m_useRowInformation and !adjacent(thisStrip, thisRow, previousStrip, previousRow)) or
544 (not m_useRowInformation and !adjacent(thisStrip, previousStrip)))) {
545
546 // Add this group to existing groups (and flush)
547 //
548 cache.idGroups.push_back(cache.currentVector);
549 cache.currentVector.clear();
550
551 cache.tbinGroups.push_back(hitsInThirdTimeBin);
552 hitsInThirdTimeBin = 0;
553 stripCount = 0;
554 }
555
556 // Only use clusters with certain time bit patterns if m_timeBinStr set
557
558 const SCT3_RawData* pRawData3 = dynamic_cast<const SCT3_RawData*>(pRawData);
559 //sroe: coverity 31562
560 if (!pRawData3) {
561 ATH_MSG_ERROR("Casting into SCT3_RawData failed. This is probably caused by use of an old RDO file.");
562 return nullptr;
563 }
564
565 int timeBin = pRawData3->getTimeBin();
566 std::bitset<3> timePattern(static_cast<unsigned long>(timeBin));
567
568 bool passTiming = true;
569
570 if (!m_timeBinStr.empty()) passTiming = testTimeBinsN(timePattern);
571
572 // Now we are either (a) pushing more contiguous strips onto an existing vector
573 // or (b) pushing a new set of ids onto an empty vector
574 //
575 if (passTiming) {
576 unsigned int nBadStrips(0);
577 unsigned int max_strip = std::min( static_cast<unsigned int>(thisStrip+nStrips), static_cast<unsigned int>(idHelper.strip_max(waferId)+1) );
578
579 if (thisStrip+nStrips > max_strip) {
580 ATH_MSG_DEBUG("SCT strip range exceeds bounds: strip range " << thisStrip << " .. + " << nStrips << " = " << (thisStrip+nStrips)
581 << " !<= " << max_strip );
582 }
583 for (unsigned int sn=thisStrip; sn < max_strip; ++sn) {
584 Identifier stripId = m_useRowInformation ? idHelper.strip_id(waferId,thisRow,sn) : idHelper.strip_id(waferId,sn);
585 if (!isBad(sctDetElStatus, idHelper, waferHash, stripId, ctx)) {
586 cache.currentVector.push_back(stripId);
587 } else {
588 cache.currentVector.push_back(badId);
589 ++nBadStrips;
590 }
591 if (stripCount < 16) {
592 hitsInThirdTimeBin = hitsInThirdTimeBin | (timePattern.test(0) << stripCount);
593 }
594 ++stripCount;
595 }
596
597 if (cache.currentVector.size() == nBadStrips) {
598 cache.currentVector.clear();
599 } else if (nBadStrips) {
600 cache.currentVector=recluster(cache.currentVector, cache.idGroups);
601 }
602 }
603
604 if (not cache.currentVector.empty()) {
605 // Gives the last strip number in the cluster
606 //
607 previousStrip = idHelper.strip(cache.currentVector.back());
608 if (m_useRowInformation) previousRow = idHelper.row(cache.currentVector.back());
609 }
610 }
611
612 // Still need to add this last vector
613 //
614 if (not cache.currentVector.empty()) {
615 cache.idGroups.push_back(cache.currentVector);
616 cache.tbinGroups.push_back(hitsInThirdTimeBin);
617 hitsInThirdTimeBin=0;
618 }
619
620 // Find detector element for these digits
621 //
622 IdentifierHash idHash = collection.identifyHash();
624 const InDetDD::SiDetectorElementCollection* sctDetEle(*sctDetEleHandle);
625 if (not sctDetEleHandle.isValid() or sctDetEle==nullptr) {
626 ATH_MSG_FATAL(m_SCTDetEleCollKey.fullKey() << " is not available.");
627 return nullptr;
628 }
629 const InDetDD::SiDetectorElement* element(sctDetEle->getDetectorElement(idHash));
630 if (!element) {
631 ATH_MSG_WARNING("Element not in the element map, hash = " << idHash);
632 return nullptr;
633 }
634
635 const InDetDD::SCT_ModuleSideDesign* design = (dynamic_cast<const InDetDD::SCT_ModuleSideDesign*>(&element->design()));
636 if(design==nullptr) return nullptr;
637
638 SCT_ClusterCollection* clusterCollection = new SCT_ClusterCollection(idHash);
639 Identifier elementID = collection.identify();
640 clusterCollection->setIdentifier(elementID);
641 clusterCollection->reserve(cache.idGroups.size());
642 if(dataItemsPool){
643 clusterCollection->clear(SG::VIEW_ELEMENTS);
644 }
645
646 int clusterNumber = 0;
647
648 // All strips are assumed to be the same width.
649 //
650 std::vector<IdVec_t>::iterator pGroup = cache.idGroups.begin();
651 std::vector<IdVec_t>::iterator lastGroup = cache.idGroups.end();
652 std::vector<uint16_t>::iterator tbinIter = cache.tbinGroups.begin();
653
654 // If clusters have been split due to bad strips, would require a whole lot
655 // of new logic to recalculate hitsInThirdTimeBin word - instead, just find
656 // when this is the case here, and set hitsInThirdTimeBin to zero later on
657 //
658 double iphipitch = 1./element->phiPitch();
659 double shift = m_lorentzAngleTool->getLorentzShift(idHash,ctx);
660 double stripPitch = design->stripPitch();
661 bool badStripInClusterOnThisModuleSide = (cache.idGroups.size() != cache.tbinGroups.size());
662 bool rotate = (element->design().shape() == InDetDD::Trapezoid || element->design().shape() == InDetDD::Annulus);
663 double stripL = 0.;
664 double COV11 = 0.;
665
666 if (not rotate) {
667 stripL = design->etaPitch();
668 COV11 = stripL*stripL*(1./12.);
669 }
670
671 for (; pGroup!=lastGroup; ++pGroup) {
672 int nStrips = pGroup->size();
673 double dnStrips = static_cast<double>(nStrips);
674 Identifier clusterId = pGroup->front();
675
676 int firstStrip = idHelper.strip(clusterId);
677 double width = stripPitch;
680 int row = idHelper.row(clusterId); //This is always 0 - should consider dropping
681 centre = element->rawLocalPositionOfCell(design->strip1Dim(firstStrip, row));
682 if (nStrips > 1) {
683 InDetDD::SiLocalPosition lastStripPos(element->rawLocalPositionOfCell(design->strip1Dim(firstStrip+nStrips-1, row)));
684 centre = (centre+lastStripPos)*.5;
685 width *=dnStrips;
686 }
687 } else {
688 DimensionAndPosition clusterDim = clusterDimensions(idHelper.strip(pGroup->front()), idHelper.strip(pGroup->back()), element, idHelper);
689 centre = clusterDim.centre;
690 width = clusterDim.width;
691 }
692
693 Amg::Vector2D localPos{centre.xPhi(), centre.xEta()};
694 Amg::Vector2D locpos{centre.xPhi()+shift, centre.xEta()};
695
696 // Now make a SiCluster
697 //
698 double x = 0.;
699 // single strip - resolution close to pitch/sqrt(12)
700 // two-strip hits: better resolution, approx. 40% lower
701 // lines taken from ClusterMakerTool::sctCluster
702 if (nStrips == 1) {
703 x = 1.05*width;
704 } else {
705 if (nStrips == 2) {
706 x = 0.27*width;
707 } else {
708 x = width;
709 }
710 }
711
712 double V[4] = {x*x*(1./12.), 0., 0., COV11};
713
714 if (rotate) {
715 // Find length of strip at centre
716 //
717 std::pair<InDetDD::SiLocalPosition, InDetDD::SiLocalPosition> ends(design->endsOfStrip(centre));
718 stripL = std::abs(ends.first.xEta()-ends.second.xEta());
719
720 double w = element->phiPitch(localPos)*iphipitch;
721 double sn = element->sinStereoLocal(localPos);
722 double sn2 = sn*sn;
723 double cs2 = 1.-sn2;
724 double v0 = V[0]*w*w;
725 double v1 = stripL*stripL*(1./12.);
726 V[0] = cs2*v0+sn2*v1;
727 V[1] = V[2] = sn*sqrt(cs2)*(v0-v1);
728 V[3] = sn2*v0+cs2*v1;
729 }
730
731 auto errorMatrix = Amg::MatrixX(2,2);
732 errorMatrix<<V[0],V[1],V[2],V[3];
733
734 SiWidth siWidth{Amg::Vector2D(dnStrips,1.), Amg::Vector2D(width,stripL)};
735
736 SCT_Cluster* cluster = nullptr;
737 if (dataItemsPool) {
738 cluster = dataItemsPool->nextElementPtr();
739 (*cluster) = SCT_Cluster{clusterId, locpos, std::move(*pGroup),
740 siWidth, element, std::move(errorMatrix)};
741
742 } else {
743 cluster = new SCT_Cluster{clusterId, locpos, std::move(*pGroup),
744 siWidth, element, std::move(errorMatrix)};
745 }
746
747 cluster->setHashAndIndex(idHash, clusterNumber);
748
749 if (tbinIter != cache.tbinGroups.end()) {
750 cluster->setHitsInThirdTimeBin(*tbinIter);
751 ++tbinIter;
752 }
753
754 // clusters had been split - recalculating HitsInThirdTimeBin too difficult to be worthwhile for this rare corner case..
755 //
756 if (badStripInClusterOnThisModuleSide) cluster->setHitsInThirdTimeBin(0);
757
758 clusterCollection->push_back(cluster);
759 clusterNumber++;
760 }
761 return clusterCollection;
762 }
763
765 SCT_ClusteringTool::clusterDimensions(int firstStrip, int lastStrip,
766 const InDetDD::SiDetectorElement* pElement,
767 const SCT_ID& /*idHelper*/) { //since a range check on strip numbers was removed, idHelper is no longer needed here
768 const int nStrips(lastStrip - firstStrip + 1);
769 // Consider strips before and after (in case nStrips=1), both are guaranteed
770 // to return sensible results, even for end strips
771 const InDetDD::SiCellId cell1(firstStrip - 1);
772 const InDetDD::SiCellId cell2(lastStrip + 1);
773 const InDetDD::SiLocalPosition firstStripPos(pElement->rawLocalPositionOfCell(cell1));
774 const InDetDD::SiLocalPosition lastStripPos(pElement->rawLocalPositionOfCell(cell2));
775 const double width((static_cast<double>(nStrips)/static_cast<double>(nStrips+1))*( lastStripPos.xPhi()-firstStripPos.xPhi()));
776 const InDetDD::SiLocalPosition centre((firstStripPos+lastStripPos)*0.5);
778 }
779
781 SCT_ClusteringTool::clusterDimensionsInclRow(int firstStrip, int lastStrip, int row,
782 const InDetDD::SiDetectorElement* pElement, const InDetDD::SCT_ModuleSideDesign* design) {
783 const int nStrips(lastStrip - firstStrip + 1);
784 const int firstStrip1D = design->strip1Dim(firstStrip, row);
785 const int lastStrip1D = design->strip1Dim(lastStrip, row);
786 const double stripPitch = design->stripPitch();
787 const InDetDD::SiCellId cell1(firstStrip1D);
788 const InDetDD::SiCellId cell2(lastStrip1D);
789 const InDetDD::SiLocalPosition firstStripPos(pElement->rawLocalPositionOfCell(cell1));
790 const InDetDD::SiLocalPosition lastStripPos(pElement->rawLocalPositionOfCell(cell2));
791 const double width(nStrips*stripPitch);
792 const InDetDD::SiLocalPosition centre((firstStripPos+lastStripPos)*0.5);
794 }
795}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
This class provides an interface to generate or decode an identifier for the upper levels of the dete...
static const ITkStripOnlineId invalidId
Header containing the InDetHierarchy enum, to avoid pulling in a class every time it is needed and na...
Header file for SCT_ClusteringTool.
header file for SCT_ReClustering class
void rotate(double angler, GeoTrf::Vector2D &vector)
const double width
#define x
a typed memory pool that saves time spent allocation small object.
Definition DataPool.h:63
pointer nextElementPtr()
obtain the next available element in pool by pointer pool is resized if its limit has been reached On...
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
bool empty() const noexcept
Returns true if the collection is empty.
This is a "hash" representation of an Identifier.
bool is_valid() const
Check if id is in a valid state.
virtual DetectorShape shape() const
Shape of element.
virtual double etaPitch() const =0
Barrel module design description for the SCT.
Design descriptor for forward modules in the SCT, carries the bounds, and readout information.
Base class for the SCT module side design, extended by the Forward and Barrel module design.
virtual double stripPitch(const SiLocalPosition &chargePos) const =0
give the strip pitch (dependence on position needed for forward)
virtual int strip1Dim(int strip, int row) const override
only relevant for SCT.
virtual std::pair< SiLocalPosition, SiLocalPosition > endsOfStrip(const SiLocalPosition &position) const override=0
give the ends of strips
Identifier for the strip or pixel cell.
Definition SiCellId.h:29
Class to hold the SiDetectorElement objects to be put in the detector store.
const SiDetectorElement * getDetectorElement(const IdentifierHash &hash) const
Class to hold geometrical description of a silicon detector element.
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
double phiPitch() const
Pitch (inline methods)
double sinStereoLocal(const Amg::Vector2D &localPos) const
Angle of strip in local frame with respect to the etaAxis.
Class to represent a position in the natural frame of a silicon sensor, for Pixel and SCT For Pixel: ...
double xPhi() const
position along phi direction:
double xEta() const
position along eta direction:
Amg::Vector2D rawLocalPositionOfCell(const SiCellId &cellId) const
Returns position (center) of cell.
virtual Identifier identify() const override final
virtual IdentifierHash identifyHash() const override final
virtual Identifier identify() const override final
void setHitsInThirdTimeBin(uint16_t hitsInThirdTimeBin)
Setter method of timing.
static bool testTimeBinsX1X(int timeBin)
virtual StatusCode initialize() override
Retrieve the necessary services in initialize.
SCT_ClusterCollection * fastClusterize(const InDetRawDataCollection< SCT_RDORawData > &RDOs, const SCT_ID &idHelper, const InDet::SiDetectorElementStatus *sctDetElementStatus, SCTClusteringCache &cache, DataPool< SCT_Cluster > *dataItemsPool, const EventContext &ctx) const
A new fast method originally implemented for ITk.
int m_timeBinBits[3]
Time bin bits for timing requirement.
static bool testTimeBins01X(int timeBin)
SCT_ClusterCollection * clusterize(const InDetRawDataCollection< SCT_RDORawData > &RDOs, const SCT_ID &idHelper, const InDet::SiDetectorElementStatus *sctDetElementStatus, SCTClusteringCache &cache, DataPool< SCT_Cluster > *dataItemsPool, const EventContext &ctx) const override
Clusterize method the SCT RDOs. This method is the main one of this class.
bool testTimeBins(int timeBin) const
ToolHandle< ClusterMakerTool > m_clusterMaker
SG::ReadHandleKey< InDet::SiDetectorElementStatus > m_sctDetElStatus
Optional read handle to get status data to test whether a SCT detector element is good.
void addStripsToClusterWithChecks(const Identifier &firstStripId, unsigned int nStrips, IdVec_t &clusterVector, std::vector< IdVec_t > &idGroups, const SCT_ID &idHelper, const InDet::SiDetectorElementStatus *det_el_status, const EventContext &ctx) const
Add strips to a cluster vector checking for bad strips.
bool isBad(const InDet::SiDetectorElementStatus *sctDetElStatus, const SCT_ID &sctID, const IdentifierHash &waferHash, const Identifier &stripId, const EventContext &ctx) const
In-class facade on the 'isGood' method for a strip identifier.
StatusCode decodeTimeBins()
Convert time bin string to array of 3 bits.
static DimensionAndPosition clusterDimensionsInclRow(int firstStrip, int lastStrip, int row, const InDetDD::SiDetectorElement *element, const InDetDD::SCT_ModuleSideDesign *design)
Calculate the cluster position and width given the first,last strip, and row numbers for this element...
ToolHandle< ISiLorentzAngleTool > m_lorentzAngleTool
std::vector< Identifier > IdVec_t
void addStripsToClusterInclRows(const Identifier &firstStripId, unsigned int nStrips, IdVec_t &clusterVector, std::vector< IdVec_t > &idGroups, const SCT_ID &idHelper, const InDet::SiDetectorElementStatus *det_el_status, const EventContext &ctx) const
Add strips to a cluster vector including row variable for ITk.
bool testTimeBinsN(const std::bitset< 3 > &timePattern) const
IdVec_t recluster(IdVec_t &clusterVector, std::vector< IdVec_t > &idGroups) const
Recluster the current vector, splitting on bad strips, and insert those new groups to the idGroups ve...
StatusCode decodeTimeBin(char timeBin, int &bit) const
Convert a single time bin char to an int, bit is modified.
static void addStripsToCluster(const Identifier &firstStripId, unsigned int nStrips, IdVec_t &clusterVector, const SCT_ID &idHelper)
Add strips to a cluster vector without checking for bad strips.
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_SCTDetEleCollKey
static DimensionAndPosition clusterDimensions(int firstStrip, int lastStrip, const InDetDD::SiDetectorElement *element, const SCT_ID &idHelper)
Calculate the cluster position and width given the first and last strip numbers for this element.
SCT_ClusteringTool(const std::string &type, const std::string &name, const IInterface *parent)
Normal constructor for an AlgTool; 'properties' are also declared here.
ToolHandle< IInDetConditionsTool > m_conditionsTool
bool operator()(const SCT_RDORawData *rdo1, const SCT_RDORawData *rdo2)
Trk::PrepRawDataCollection< SCT_Cluster > SCT_ClusterCollection
int getTimeBin() const
This is an Identifier helper class for the SCT subdetector.
Definition SCT_ID.h:68
int layer_disk(const Identifier &id) const
Definition SCT_ID.h:687
IdentifierHash wafer_hash(const Identifier &wafer_id) const
wafer hash from id - optimized
Definition SCT_ID.h:487
Identifier wafer_id(int barrel_ec, int layer_disk, int phi_module, int eta_module, int side) const
For a single side of module.
Definition SCT_ID.h:459
int strip_max(const Identifier &id) const
Definition SCT_ID.cxx:188
int row(const Identifier &id) const
Definition SCT_ID.h:711
int strip(const Identifier &id) const
Definition SCT_ID.h:717
int barrel_ec(const Identifier &id) const
Values of different levels (failure returns 0)
Definition SCT_ID.h:681
Identifier strip_id(int barrel_ec, int layer_disk, int phi_module, int eta_module, int side, int strip) const
For an individual strip.
Definition SCT_ID.h:530
bool is_barrel(const Identifier &id) const
Test for barrel - WARNING: id MUST be sct id, otherwise answer is not accurate. Use SiliconID for gen...
Definition SCT_ID.h:674
void setHashAndIndex(unsigned short collHash, unsigned short objIndex)
TEMP for testing: might make some classes friends later ...
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Matrix< double, 2, 1 > Vector2D
Primary Vertex Finder.
bool adjacent(unsigned int strip1, unsigned int strip2)
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
std::vector< IdVec_t > idGroups
std::vector< uint16_t > tbinGroups
In-class struct to store the centre and width of a cluster.