ATLAS Offline Software
Loading...
Searching...
No Matches
CscThresholdClusterBuilderTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5// CscThresholdClusterBuilderTool.cxx
7
8#include <sstream>
9
16#include "Gaudi/Property.h"
21#include "TrkSurfaces/Surface.h"
22
31using std::ostringstream;
32using std::setw;
33using std::vector;
34
35//******************************************************************************
36// Local definitions.
37namespace {
38 //******************************************************************************
39
40 // Convert chamber identifier to string.
41 std::string chamber(int istation, int zsec, int phi) {
42 ostringstream ssout;
43 if (istation == 1)
44 ssout << "CSS";
45 else if (istation == 2)
46 ssout << "CSL";
47 else
48 ssout << "???";
49 if (zsec == -1)
50 ssout << "-";
51 else if (zsec == 1)
52 ssout << "+";
53 else
54 ssout << "?";
55 ssout << phi;
56 return ssout.str();
57 }
58
59 // Convert measphi to string.
60 std::string setaphi(bool measphi) {
61 if (measphi) return "phi";
62 return "eta";
63 }
64
65 //******************************************************************************
66} // end unnamed namespace
67//******************************************************************************
68
69CscThresholdClusterBuilderTool::CscThresholdClusterBuilderTool(const std::string& type, const std::string& aname,
70 const IInterface* parent) :
71 AthAlgTool(type, aname, parent), m_noiseOption(rms), m_digit_key("CSC_Measurements") {
72 declareInterface<ICscClusterBuilder>(this);
73
74 declareProperty("threshold", m_threshold = 20000.0);
75 declareProperty("kFactor", m_kFactor = 6.5);
76 declareProperty("noiseOption", m_noiseOptionStr = "f001");
77 declareProperty("digit_key", m_digit_key);
78 declareProperty("makeNarrowClusterThreeStrips", m_makeNarrowClusterThreeStrips = true);
79}
80
81//******************************************************************************
82
83// Destructor.
84
86
87//******************************************************************************
88
90 // Display algorithm properties.
91 ATH_MSG_DEBUG("Properties for " << name() << ":");
92 ATH_MSG_DEBUG(" Strip threshold is Max( " << m_threshold << ", " << m_kFactor << "*stripNoise ) where stripNoise is from "
94 ATH_CHECK(m_digit_key.initialize());
95 if (m_noiseOptionStr != "rms" && m_noiseOptionStr != "sigma" && m_noiseOptionStr != "f001") {
96 ATH_MSG_DEBUG(" noiseOption is not among rms/sigma/f001. rms is used for default!!");
97 m_noiseOptionStr = "rms";
98 }
99 if (m_noiseOptionStr == "rms")
101 else if (m_noiseOptionStr == "sigma")
103 else if (m_noiseOptionStr == "f001")
105
106 ATH_MSG_DEBUG(" Strip fitter is " << m_pstrip_fitter.typeAndName());
107 ATH_MSG_DEBUG(" Default cluster fitter is " << m_pfitter_def.typeAndName());
108 ATH_MSG_DEBUG(" Precision cluster fitter is " << m_pfitter_prec.typeAndName());
109 ATH_MSG_DEBUG(" Split cluster fitter is " << m_pfitter_split.typeAndName());
110 ATH_MSG_DEBUG(" Input digit key is " << m_digit_key.key());
111
112 // CSC calibratin tool for the Condtiions Data base access //
114
115 // Retrieve the strip fitting tool.
117 ATH_MSG_DEBUG("Retrieved strip fitting tool " << m_pstrip_fitter);
118
119 // Retrieve the default cluster fitting tool.
121 ATH_MSG_DEBUG("Retrieved CSC default cluster fitting tool");
122
123 // Retrieve the precision cluster fitting tool.
125 ATH_MSG_DEBUG("Retrieved CSC precision cluster fitting tool");
126
127 // Retrieve the split cluster fitting tool.
129 ATH_MSG_DEBUG("Retrieved CSC split cluster fitting tool");
130
131 // retrieve MuonDetectorManager from the conditions store
132 ATH_CHECK(m_DetectorManagerKey.initialize());
133 ATH_CHECK(m_idHelperSvc.retrieve());
134
135 return StatusCode::SUCCESS;
136}
137
138//******************************************************************************
139
140StatusCode CscThresholdClusterBuilderTool::getClusters(std::vector<IdentifierHash>& givenIDs, std::vector<IdentifierHash>& decodedIds,
141 CscPrepDataContainer* object) {
142 // clear output vector of selected data collections containing data
143 decodedIds.clear();
144 if (!givenIDs.empty()) {
145 for (unsigned int i = 0; i < givenIDs.size(); ++i) {
146 if (getClusters(givenIDs[i], decodedIds, object).isFailure()) {
147 ATH_MSG_ERROR("Unable to decode CSC RDO " << i << "th into CSC PrepRawData");
148 return StatusCode::RECOVERABLE;
149 }
150 }
151 } else {
152 // Clusterization is done for every area
153 if (getClusters(decodedIds, object).isFailure()) {
154 ATH_MSG_ERROR("Unable to decode CSC RDO into CSC PrepRawData");
155 return StatusCode::RECOVERABLE;
156 }
157 }
158
159 return StatusCode::SUCCESS;
160}
161
162//******************************************************************************
163
164StatusCode CscThresholdClusterBuilderTool::getClusters(IdentifierHash givenHashId, std::vector<IdentifierHash>& decodedIds,
165 Muon::CscPrepDataContainer* pclusters) {
166 // identifiers of collections already decoded and stored in the container will be skipped
167 if (pclusters->indexFindPtr(givenHashId) != nullptr) {
168 decodedIds.push_back(givenHashId);
169 ATH_MSG_DEBUG("A collection already exists in the container for offline id hash. " << (int)givenHashId);
170 return StatusCode::SUCCESS;
171 }
172
173 // Retrieve the CSC digits for this event.
175 if (pdigcon.isValid()) {
176 ATH_MSG_DEBUG("Retrieved strip container " << m_digit_key.key() << " with " << pdigcon->size() << " entries.");
177 } else {
178 ATH_MSG_WARNING("Failure to retrieve strip container " << m_digit_key.key());
179 return StatusCode::SUCCESS;
180 }
181
182 //**********************************************
183 // retrieve specific collection for the givenID
184 const CscStripPrepDataCollection* col = pdigcon->indexFindPtr(givenHashId);
185 if (nullptr == col) {
186 unsigned int coll_hash = givenHashId;
187 ATH_MSG_WARNING("Specific CSC Strip PrepData collection retrieving failed for collection hash = " << coll_hash);
188 return StatusCode::SUCCESS;
189 }
190
191 ATH_MSG_DEBUG("Retrieved " << col->size() << " CSC Strip PrepDatas.");
192
193 Identifier colid = col->identify();
194 int istation = m_idHelperSvc->cscIdHelper().stationName(colid) - 49;
195 int zsec = m_idHelperSvc->cscIdHelper().stationEta(colid);
196 int phisec = m_idHelperSvc->cscIdHelper().stationPhi(colid);
197
198 ATH_MSG_DEBUG(" Strip collection " << chamber(istation, zsec, phisec) << " has " << col->size() << " strips");
199
200 // Create arrays to hold digits and cathode plane parameters.
201 vector<const CscStripPrepData*> strips[8];
202 int maxstrip[8] = {0, 0, 0, 0, 0, 0, 0, 0};
203
204 // retrieve MuonDetectorManager from the conditions store
206 const MuonGM::MuonDetectorManager* MuonDetMgr = DetectorManagerHandle.cptr();
207 if (MuonDetMgr == nullptr) {
208 ATH_MSG_ERROR("Null pointer to the MuonDetectorManager conditions object");
209 return StatusCode::FAILURE;
210 }
211
212 IdentifierHash hash;
213 // Loop over digits and fill these arrays.
214 for (CscStripPrepDataCollection::const_iterator idig = col->begin(); idig != col->end(); ++idig) {
215 const CscStripPrepData& dig = **idig;
216 Identifier did = dig.identify();
217 hash = dig.collectionHash();
218 const CscReadoutElement* pro = MuonDetMgr->getCscReadoutElement(did);
219 int wlay = m_idHelperSvc->cscIdHelper().wireLayer(did);
220 int measphi = m_idHelperSvc->cscIdHelper().measuresPhi(did);
221 int idx = 2 * (wlay - 1) + measphi;
222 // First entry for a cathode plane, initialize.
223 if (maxstrip[idx] == 0) {
224 maxstrip[idx] = pro->maxNumberOfStrips(measphi);
225 for (int istrip = 0; istrip < maxstrip[idx]; ++istrip) strips[idx].push_back(nullptr);
226 }
227 int istrip = m_idHelperSvc->cscIdHelper().strip(did) - 1;
228 if (istrip < 0 || istrip >= maxstrip[idx]) {
229 ATH_MSG_WARNING("Invalid strip number");
230 continue;
231 }
232 strips[idx][istrip] = &dig;
233 }
234
235 // Cluster.
236 CscPrepDataCollection* newCollection = nullptr;
237 for (int measphi = 0; measphi < 2; ++measphi) {
238 for (int wlay = 1; wlay < 5; ++wlay) {
239 int idx = 2 * (wlay - 1) + measphi;
240 if (maxstrip[idx]) {
241 make_clusters(measphi, strips[idx], newCollection);
242 ATH_MSG_DEBUG(" " << wlay << "th layer ");
243 }
244 }
245 }
246 if (newCollection) {
247 if (pclusters->addCollection(newCollection, hash).isFailure()) {
248 ATH_MSG_ERROR("Couldn't add CscPrepdataCollection to container!");
249 return StatusCode::RECOVERABLE;
250 }
251 decodedIds.push_back(hash); // Record that this collection contains data
252 }
253
254 return StatusCode::SUCCESS;
255}
256
257//******************************************************************************
258
259StatusCode CscThresholdClusterBuilderTool::getClusters(std::vector<IdentifierHash>& decodedIds, Muon::CscPrepDataContainer* pclusters) {
260 // Retrieve the CSC digits for this event.
262 if (pdigcon.isValid()) {
263 ATH_MSG_DEBUG("Retrieved strip container " << m_digit_key.key() << " with " << pdigcon->size() << " entries.");
264 } else {
265 ATH_MSG_WARNING("Failure to retrieve strip container " << m_digit_key.key());
266 return StatusCode::SUCCESS;
267 }
268
269 // Loop over digit collections.
270 // This a loop over chambers (each with 4 wire planes).
271 const CscStripPrepDataContainer& con = *pdigcon;
272 for (CscStripPrepDataContainer::const_iterator icol = con.begin(); icol != con.end(); ++icol) {
273 const CscStripPrepDataCollection& col = **icol;
274 // check if the collection is already used
275 if (pclusters->indexFindPtr(col.identifyHash()) != nullptr) {
276 // store the identifier hash and continue
277 decodedIds.push_back(col.identifyHash());
278 continue;
279 }
280 Identifier colid = col.identify();
281 int istation = m_idHelperSvc->cscIdHelper().stationName(colid) - 49;
282 int zsec = m_idHelperSvc->cscIdHelper().stationEta(colid);
283 int phisec = m_idHelperSvc->cscIdHelper().stationPhi(colid);
284 ATH_MSG_DEBUG("**Strip collection " << chamber(istation, zsec, phisec) << " sector " << m_idHelperSvc->cscIdHelper().sector(colid)
285 << " has " << col.size() << " strips");
286
287 // Create arrays to hold digits and cathode plane parameters.
288 vector<const CscStripPrepData*> strips[8];
289 int maxstrip[8] = {0, 0, 0, 0, 0, 0, 0, 0};
290
291 // retrieve MuonDetectorManager from the conditions store
293 const MuonGM::MuonDetectorManager* MuonDetMgr = DetectorManagerHandle.cptr();
294 if (MuonDetMgr == nullptr) {
295 ATH_MSG_ERROR("Null pointer to the MuonDetectorManager conditions object");
296 return StatusCode::FAILURE;
297 }
298
299 IdentifierHash hash;
300 // Loop over digits and fill these arrays.
301 for (CscStripPrepDataCollection::const_iterator idig = col.begin(); idig != col.end(); ++idig) {
302 const CscStripPrepData& dig = **idig;
303 Identifier did = dig.identify();
304 hash = dig.collectionHash();
305 const CscReadoutElement* pro = MuonDetMgr->getCscReadoutElement(did);
306 int wlay = m_idHelperSvc->cscIdHelper().wireLayer(did);
307 int measphi = m_idHelperSvc->cscIdHelper().measuresPhi(did);
308 int idx = 2 * (wlay - 1) + measphi;
309 // First entry for a cathode plane, initialize.
310 if (maxstrip[idx] == 0) {
311 maxstrip[idx] = pro->maxNumberOfStrips(measphi);
312 for (int istrip = 0; istrip < maxstrip[idx]; ++istrip) strips[idx].push_back(nullptr);
313 }
314 int istrip = m_idHelperSvc->cscIdHelper().strip(did) - 1;
315 if (istrip < 0 || istrip >= maxstrip[idx]) {
316 ATH_MSG_WARNING("Invalid strip number");
317 continue;
318 }
319 strips[idx][istrip] = &dig;
320 }
321
322 // Cluster.
323 CscPrepDataCollection* newCollection = nullptr;
324 for (int measphi = 0; measphi < 2; ++measphi) {
325 for (int wlay = 1; wlay < 5; ++wlay) {
326 int idx = 2 * (wlay - 1) + measphi;
327 if (maxstrip[idx]) {
328 ATH_MSG_DEBUG("*** " << chamber(istation, zsec, phisec) << " sector " << m_idHelperSvc->cscIdHelper().sector(colid)
329 << " " << wlay << "th layer ");
330 make_clusters(measphi, strips[idx], newCollection);
331 }
332 }
333 }
334 if (newCollection) {
335 if (pclusters->addCollection(newCollection, hash).isFailure()) {
336 ATH_MSG_ERROR("Couldn't add CscPrepdataCollection to container!");
337 return StatusCode::FAILURE;
338 }
339 decodedIds.push_back(hash); // Record that this collection contains data
340 }
341 } // end loop over chambers
342
343 return StatusCode::SUCCESS;
344}
345//******************************************************************************
346
348 ATH_MSG_VERBOSE("Finalizing " << name());
349 return StatusCode::SUCCESS;
350}
351
352//******************************************************************************
353
354// Build clusters.
355// dump - whether to write messages
356// dstrip = CSC digit pointer for each strip.
357// qstrip - charge on each strip
358// Note strip numbering is 0, maxstA, shifted by 1 from ATLAS strip numbers.
359// Center of strip is at pitch * (istrip + 0.5 - maxstrip/2).
360
361// NOTE: vector<CscStripPrepData*> strips is filled up with full strips (48/192)
362// some of them have null pointer. Useful to find adjacent strip CscStripPrepData...
363
364int CscThresholdClusterBuilderTool::make_clusters(bool measphi, const vector<const CscStripPrepData*>& strips,
365 CscPrepDataCollection*& newCollection) {
366 // Loop over channels.
367 unsigned int maxstrip = strips.size();
368
369 ATH_MSG_DEBUG(" Clustering for " << setaphi(measphi) << " plane with " << maxstrip << " strips");
370
372 // Phase I:
373 //
374 // Loop over strips and fetch the charge and time for each.
375 // Also set flag indicating if this strip has pointer and charge is above threshold(active)
378 std::vector<bool> astrip; // check active strip
379 std::vector<bool> bstrip; // check bad strip
380 IdentifierHash cscHashId;
381
382 // Always [0, 191] or [0, 47]
383 for (unsigned int istrip = 0; istrip < strips.size(); ++istrip) {
384 const CscStripPrepData* pstrip = strips[istrip];
386 bool active = false;
387 bool isBadChannel = false;
388 if (pstrip) {
389 if (!newCollection) {
390 Identifier elementId = m_idHelperSvc->cscIdHelper().elementID(pstrip->identify());
391 cscHashId = pstrip->collectionHash();
392 newCollection = new CscPrepDataCollection(cscHashId);
393 newCollection->setIdentifier(elementId);
394 }
395 res = m_pstrip_fitter->fit(*pstrip);
396
397 IdentifierHash stripHash;
398 Identifier stripId = pstrip->identify();
399 if (m_idHelperSvc->cscIdHelper().get_channel_hash(stripId, stripHash)) {
400 ATH_MSG_WARNING("Unable to get CSC striphash id "
401 << " the identifier is \n" << stripId);
402 }
403
404 if (res.stripStatus == Muon::CscStrStatHot || res.stripStatus == Muon::CscStrStatDead) isBadChannel = true;
405
406 float stripNoise = 0;
407 if (m_noiseOption == rms) {
408 stripNoise = m_cscCalibTool->stripRMS(stripHash);
409 } else if (m_noiseOption == sigma) {
410 stripNoise = m_cscCalibTool->stripNoise(stripHash);
411 } else if (m_noiseOption == f001) { // f001 is rawADC +1
412 stripNoise = m_cscCalibTool->stripF001(stripHash) - m_cscCalibTool->stripPedestal(stripHash);
413 stripNoise /= 3.251;
414 }
415
416 active = res.charge >= m_threshold && res.charge >= m_kFactor * stripNoise;
417 if (isBadChannel) active = false; // Let's remove Bad channel First...
418
419 if (msgLvl(MSG::DEBUG)) {
420 // Log message.
421 ostringstream strlog;
422 strlog << " Strip " << setw(3) << istrip + 1 << ": charge= " << setw(7) << int(res.charge) << " dcharge= " << setw(7)
423 << int(res.dcharge);
424 if (std::fabs(res.time) < 1e8)
425 strlog << " time=" << setw(3) << int(res.time + 0.5);
426 else
427 strlog << " time=OVERFLOW";
428 if (active)
429 strlog << " *";
430 else if (isBadChannel)
431 strlog << " b";
432 else
433 strlog << " .";
434 if (res.status)
435 strlog << " x";
436 else
437 strlog << " o";
438 strlog << " :" << res.status;
439 ATH_MSG_DEBUG(strlog.str());
440 }
441 }
442 allStripfits.push_back(res);
443 astrip.push_back(active);
444 bstrip.push_back(isBadChannel);
445 }
446
448 // Phase II:
449 //
450 // Bad Channel recovery in case of strip above strip being nearby
452
453 // 1. identify strips to recover
454 std::vector<bool> rstrip; // check recover strip
455 bool IsAnyStripRecovered = false;
456 for (unsigned int istrip = 0; istrip < strips.size(); ++istrip) {
457 bool adjacentActive = false;
458 if (bstrip[istrip]) {
459 if (istrip > 0 && astrip[istrip - 1]) adjacentActive = true;
460 if (istrip + 1 < strips.size() && astrip[istrip + 1]) adjacentActive = true;
461 if (adjacentActive) IsAnyStripRecovered = true;
462 }
463 rstrip.push_back(adjacentActive);
464 }
465
466 // 2. make it active if strip to recover is not active
467 if (IsAnyStripRecovered) { // This loop is needed if there is any bad strip recovered because of adjacent active strip
468
469 if (msgLvl(MSG::DEBUG)) {
470 ostringstream checklog1;
471 ostringstream checklog2;
472
473 for (unsigned int istrip = 0; istrip < strips.size(); ++istrip) {
474 if (istrip % 24 == 0) checklog1 << "\n";
475 checklog1 << int(astrip[istrip]) << " ";
476
477 if (!astrip[istrip] && rstrip[istrip]) { // not active but bad strip with adjacent strip active
478 ATH_MSG_DEBUG("**** Strip " << istrip << " is recovered!!");
479 }
480 if (istrip % 24 == 0) checklog2 << "\n";
481 checklog2 << int(astrip[istrip]) << " ";
482 }
483 ATH_MSG_DEBUG("Strip active map before and after");
484 ATH_MSG_DEBUG(checklog1.str());
485 ATH_MSG_DEBUG(checklog2.str());
486 }
487
488 for (unsigned int istrip = 0; istrip < strips.size(); ++istrip) {
489 if (!astrip[istrip] && rstrip[istrip]) { // not active but bad strip with adjacent strip active
490 astrip[istrip] = rstrip[istrip]; // insert true
491 }
492 }
493 }
495 // Phase III:
496 //
497 // Find clusters : save first strip and nstrip
499 vector<unsigned int> strip0s;
500 vector<unsigned int> nstrips;
501
502 // Loop over strips and create clusters.
503 int nstrip = 0;
504 int first_strip = 0; // First strip in the cluster.
505 bool incluster = false;
506 for (unsigned int istrip = 0; istrip < strips.size(); ++istrip) {
507 // If the current strip is not active, skip it.
508 if (!astrip[istrip]) continue;
509 assert(strips[istrip] != 0); // CscStripPrepData* pstrip = strips[istrip];
510
511 if (!incluster) {
512 incluster = true;
513 nstrip = 0;
514 first_strip = istrip;
515 }
516 ++nstrip;
517
518 // If this is not the last strip in the plane, and the next
519 // strip is active, add the next strip to the cluster.
520 if (istrip != maxstrip - 1 && astrip[istrip + 1]) continue;
521
522 // Recover narrow cluster
523 if (!measphi && nstrip < 3) {
524 bool collectLeftStrip = false;
525 bool collectRightStrip = false;
526
527 if (nstrip == 1) {
528 if (int(istrip) >= nstrip // left adjacent strip should be inside of CSC chamber >0
529 && istrip + 1 < maxstrip // the other side strip should be available < 192
530 && (allStripfits[istrip - 1].charge > 0.1 && allStripfits[istrip + 1].charge > 0.1) // charge should be positive
531 && strips[istrip - 1] && strips[istrip + 1]) { // both adjacent strip identifier should exist
532 collectLeftStrip = true;
533 collectRightStrip = true;
534 }
535 } else if (nstrip == 2) {
536 if (allStripfits[istrip - 1].charge > allStripfits[istrip].charge) { // In case of left strip not fired
537 if (int(istrip) >= nstrip // nstrip 2
538 && allStripfits[istrip - 2].charge > 0.1 // charge should be positive
539 && strips[istrip - 2]) // left strip Identifier should exist
540 collectLeftStrip = true;
541 } else { // In case of right strip not fired
542 if (istrip + 1 < maxstrip &&
543 allStripfits[istrip + 1].charge > 0.1 // charge should be positive if 0, then 0.341E-134 will enter
544 && strips[istrip + 1]) // right strip Identifier should exist
545 collectRightStrip = true;
546 }
547 }
548
549 if (collectLeftStrip) {
550 first_strip = first_strip - 1;
551 nstrip += 1;
552 }
553 if (collectRightStrip) { nstrip += 1; }
554
555 if (msgLvl(MSG::DEBUG)) {
556 // Log message.
557 ostringstream narrowlog;
558 narrowlog << " ** narrow Clusters " << first_strip + 1 << " " << nstrip << " L:R " << collectLeftStrip << " "
559 << collectRightStrip;
560 for (int i = 0; i < nstrip; ++i) { narrowlog << " " << allStripfits[first_strip + i].charge; }
561 for (int i = 0; i < nstrip; ++i) { narrowlog << " " << strips[first_strip + i]; }
562 ATH_MSG_DEBUG(narrowlog.str());
563 }
564 } // Only for eta plane nstrip <3
565
566 strip0s.push_back(first_strip);
567 nstrips.push_back(nstrip);
568
569 // Reset incluster.
570 incluster = false;
571 }
572
574 // Phase IV:
575 //
576 // Merge narrow cluster into adjacent cluster if any exists.
577 // Only for eta strips...
579 vector<unsigned int> newStrip0s;
580 vector<unsigned int> newNstrips;
581
582 int nMerged = 0; // the difference b/w old Nclu and new Nclu
583 for (unsigned int icl = 0; icl < nstrips.size(); ++icl) {
584 unsigned int nstrip = nstrips[icl];
585 unsigned int strip0 = strip0s[icl];
586
587 ATH_MSG_VERBOSE(" " << icl << "th cluster merger " << strip0 << " " << nstrip);
588
589 //#### if you find narrow cluster
590 if (!measphi) {
591 if (nstrip < 3) {
592 // at least one cluster before to check left cluster and continuous
593 if (icl > 0 && (strip0 == strip0s[icl - 1] + nstrips[icl - 1])) {
594 unsigned int newStrip0 = strip0s[icl - 1];
595 unsigned int newNstrip = nstrips[icl - 1] + nstrip;
596
597 ATH_MSG_DEBUG(" " << icl << " ** narrow Cluster merger Type I" << newStrip0 << " " << newNstrip);
598
599 newStrip0s[icl - 1 - nMerged] = newStrip0;
600 newNstrips[icl - 1 - nMerged] = newNstrip;
601 ++nMerged;
602 continue;
603 }
604 // at least one cluster after to check right cluster and continuous
605 if (icl + 1 < nstrips.size() && (strip0 + nstrip == strip0s[icl + 1])) {
606 unsigned int newStrip0 = strip0;
607 unsigned int newNstrip = nstrip + nstrips[icl + 1];
608
609 ATH_MSG_DEBUG(" " << icl << " ** narrow Cluster merger Type II" << newStrip0 << " " << newNstrip);
610
611 newStrip0s.push_back(newStrip0);
612 newNstrips.push_back(newNstrip);
613
614 icl += 1;
615 ++nMerged;
616 continue;
617 }
618 }
619 } // !measphi
620 // if nstrip >2 OR
621 // still narrow strip then just keep it...
622 newStrip0s.push_back(strip0);
623 newNstrips.push_back(nstrip);
624 } // for
625
626 if (strip0s.size() != newStrip0s.size()) {
627 ATH_MSG_DEBUG(" Phase II -> III Merged " << strip0s.size() << ":" << nstrips.size() << " " << newStrip0s.size() << ":"
628 << newNstrips.size());
629 for (unsigned int icl = 0; icl < nstrips.size(); ++icl)
630 ATH_MSG_DEBUG(" *** " << icl << " [" << strip0s[icl] << "," << strip0s[icl] + nstrips[icl] - 1 << "] " << nstrips[icl]);
631 for (unsigned int icl = 0; icl < newNstrips.size(); ++icl)
632 ATH_MSG_DEBUG(" ****** " << icl << " [" << newStrip0s[icl] << "," << newStrip0s[icl] + newNstrips[icl] - 1 << "] "
633 << newNstrips[icl]);
634 }
635
637 // Phase V:
638 //
639 // Using strip0 and nstrip fill up collection
641
643 std::vector<const CscStripPrepData*> clusterStrips;
644 clusterStrips.reserve(50);
645 std::vector<Identifier> prd_digit_ids;
646 prd_digit_ids.reserve(50);
647
648 for (unsigned int icl = 0; icl < newNstrips.size(); ++icl) { // for each cluster
649
650 ATH_MSG_VERBOSE(" Creating " << icl << "th cluster");
651
652 unsigned int nstrip = newNstrips[icl]; // only used here
653 unsigned int strip0 = newStrip0s[icl]; // only used here
654
655 sfits.clear();
656 clusterStrips.clear();
657 prd_digit_ids.clear();
658
659 for (unsigned int ist = strip0; ist < strip0 + nstrip; ++ist) {
660 const CscStripPrepData* pstrip = strips[ist];
661 const ICscClusterFitter::StripFit& sfit = allStripfits[ist];
662
663 sfits.push_back(sfit);
664 clusterStrips.push_back(pstrip);
665 prd_digit_ids.push_back(pstrip->identify());
666 }
667
668 ATH_MSG_VERBOSE(" ++++++++++++++ nstrip +++++ " << nstrip);
670 if (nstrip < 3 && m_makeNarrowClusterThreeStrips) {
674
675 bool leftToFill = false;
676 bool rightToFill = false;
677 if (nstrip == 1) {
678 leftToFill = true;
679 rightToFill = true;
680 } else {
681 if (sfits[0].charge > sfits[1].charge) {
682 leftToFill = true;
683 } else if (sfits[0].charge < sfits[1].charge) {
684 rightToFill = true;
685 } else {
686 ATH_MSG_DEBUG(" It should be CHECKED!!! ");
687 if (strip0 > 0) {
688 if (strips[strip0 - 1]) {
689 leftToFill = true;
690 } else if (strips[strip0 + 2]) {
691 rightToFill = true;
692 }
693 } else if (strips[strip0 + 2]) {
694 rightToFill = true;
695 }
696 }
697 }
698
699 ATH_MSG_VERBOSE(" strip0 nstrip filling left or right " << strip0 << " " << nstrip << " " << leftToFill << " "
700 << rightToFill);
701 ATH_MSG_VERBOSE(" sfits[0] " << sfits[0].charge);
702 if (nstrip == 2) ATH_MSG_VERBOSE(" sfits[1] " << sfits[1].charge);
703
704 for (unsigned int i = 0; i < allStripfits.size(); ++i) { ATH_MSG_VERBOSE("index " << i << " " << allStripfits[i].charge); }
705
706 if (leftToFill) {
707 // ATH_MSG_DEBUG( " Left to fill " << allStripfits[strip0-1].charge);
708 bool fillTheOtherSide = false;
709 if (strip0 == 0) {
710 fillTheOtherSide = true;
711 } else {
712 if (strips[strip0 - 1] == nullptr) fillTheOtherSide = true;
713 }
714
715 if (strip0 + nstrip >= allStripfits.size()) { fillTheOtherSide = false; }
716
717 if (!fillTheOtherSide) {
718 if (strips[strip0 - 1]) {
719 sfits.insert(sfits.begin(), allStripfits[strip0 - 1]);
720 clusterStrips.insert(clusterStrips.begin(), strips[strip0 - 1]);
721 prd_digit_ids.insert(prd_digit_ids.begin(), strips[strip0 - 1]->identify());
722 strip0--;
723 nstrip = prd_digit_ids.size();
724 }
725 } else {
726 if (strips[strip0 + nstrip]) { // for edge this can happen
727 sfits.push_back(allStripfits[strip0 + nstrip]); // This is the case for example
728 // 12799.6 39183.9 39698
729 clusterStrips.push_back(strips[strip0 + nstrip]);
730 prd_digit_ids.push_back(strips[strip0 + nstrip]->identify());
731 nstrip = prd_digit_ids.size();
732 }
733 }
734 }
735
736 if (rightToFill) {
737 bool fillTheOtherSide = false;
738 if (strip0 + nstrip >= allStripfits.size()) {
739 fillTheOtherSide = true;
740 } else {
741 if (strips[strip0 + nstrip] == nullptr) fillTheOtherSide = true;
742 }
743
744 if (strip0 == 0) { fillTheOtherSide = false; }
745
746 if (!fillTheOtherSide) {
747 if (strips[strip0 + nstrip]) {
748 sfits.push_back(allStripfits[strip0 + nstrip]);
749 clusterStrips.push_back(strips[strip0 + nstrip]);
750 prd_digit_ids.push_back(strips[strip0 + nstrip]->identify());
751 nstrip = prd_digit_ids.size();
752 }
753 } else {
754 if (strips[strip0 - 1]) { // for edge this can happen
755 sfits.insert(sfits.begin(), allStripfits[strip0 - 1]);
756 clusterStrips.insert(clusterStrips.begin(), strips[strip0 - 1]);
757 prd_digit_ids.insert(prd_digit_ids.begin(), strips[strip0 - 1]->identify());
758 strip0--;
759 nstrip = prd_digit_ids.size();
760 }
761 }
762 }
763 }
765
766 int fitresult = 99;
767 std::vector<ICscClusterFitter::Result> results;
768
769 // Precision fit.
770 if (!measphi) {
771 results = m_pfitter_prec->fit(sfits);
772 fitresult = results[0].fitStatus;
773 ATH_MSG_VERBOSE(" Performing precision fit " << m_pfitter_prec << " result return=" << fitresult);
774
775 // in case of multipeak cluster
776 if (fitresult == 6) {
777 results = m_pfitter_split->fit(sfits);
778 fitresult = results[0].fitStatus;
779 for (unsigned int i = 0; i < results.size(); ++i)
780 ATH_MSG_VERBOSE(" Performing split fit with " << m_pfitter_split << " result return=" << results[i].fitStatus);
781 }
782 }
783
784 bool precisionFitFailed = fitresult > 0 && fitresult < 20; // splitclusterFit fail => 19
785 // Default fit for phi and eta failed
786 if (measphi || precisionFitFailed) {
788 CscClusterStatus oldclustatus;
789 if (!measphi) {
790 res = results[0];
791 oldclustatus = res.clusterStatus;
792 } else {
793 oldclustatus = Muon::CscStatusSimple;
794 }
795 results = m_pfitter_def->fit(sfits);
796 if (!results.empty()) {
797 res = results[0];
798 fitresult = results[0].fitStatus;
799 if (msgLvl(MSG::VERBOSE)) {
800 ostringstream deflog;
801 deflog << " Performing default fit with " << m_pfitter_def;
802 if (fitresult) {
803 deflog << " failed: return=" << fitresult;
804 } else {
805 deflog << " succeeded";
806 }
807 ATH_MSG_VERBOSE(deflog.str());
808 }
809 // Keep the status from the first fit if it is defined.
810 if (oldclustatus != Muon::CscStatusUndefined) {
811 res.clusterStatus = oldclustatus;
812 // we want to keep oldcluster status
813 results[0] = res;
814 }
815 }
816 }
817
819 //
820 // Phase V. For multiple results, fill up collection
821 //
823 unsigned int nresults = results.size();
824 for (unsigned int ire = 0; ire < nresults; ++ire) {
825 CscClusterStatus clustatus = results[ire].clusterStatus;
826 Muon::CscTimeStatus timeStatus = results[ire].timeStatus;
827 double pos = results[ire].position;
828 double err = results[ire].dposition;
829 unsigned int id_strip = results[ire].strip; // return peak strip index (unsigned integer)
830 double cluster_charge = results[ire].charge;
831 double cluster_time = results[ire].time;
832 if (clustatus == Muon::CscStatusUndefined) ATH_MSG_DEBUG(" Csc Cluster Status is not defined.");
833
834 if (id_strip >= sfits.size()) {
835 ATH_MSG_WARNING(" Fit size check failed: ");
836 continue;
837 }
838 // Fetch the strip used to identify this cluster.
839 const CscStripPrepData* pstrip_id = nullptr;
840 if (id_strip < clusterStrips.size()) pstrip_id = clusterStrips[id_strip];
841 if (!pstrip_id) {
842 ATH_MSG_WARNING(" Fit ID check failed: ");
843 continue;
844 }
845
846 // Create ATLAS CSC cluster.
847 Identifier cluster_id = pstrip_id->identify();
848 IdentifierHash cluster_hash = pstrip_id->collectionHash();
849 int zsec = m_idHelperSvc->cscIdHelper().stationEta(cluster_id);
850 int wlay = m_idHelperSvc->cscIdHelper().wireLayer(cluster_id);
851 // This local position is in the muon (not tracking) coordinate system.
852 // retrieve MuonDetectorManager from the conditions store
854 const MuonGM::MuonDetectorManager* MuonDetMgr = DetectorManagerHandle.cptr();
855 if (MuonDetMgr == nullptr) {
856 ATH_MSG_ERROR("Null pointer to the MuonDetectorManager conditions object");
857 return 0;
858 }
859 const CscReadoutElement* pro = MuonDetMgr->getCscReadoutElement(cluster_id);
860 // Amg::Vector3D local_pos = pro->localClusterPos(zsec, wlay, measphi, pos);
861 Amg::Vector3D localTrk_pos = pro->nominalLocalClusterPos(zsec, wlay, measphi, pos);
862
863 auto cov = Amg::MatrixX(1, 1);
864 (cov)(0, 0) = err * err;
865 Amg::Vector2D plpos(measphi ? localTrk_pos.y() : localTrk_pos.z(), measphi ? localTrk_pos.z() : localTrk_pos.y());
866 if (msgLvl(MSG::DEBUG)) {
867 ATH_MSG_DEBUG(" Cluster parameters: " << nresults);
868 ATH_MSG_DEBUG(" ID strip: " << first_strip + id_strip << "(" << first_strip << ":" << id_strip << ")");
869 ATH_MSG_DEBUG(" local position: " << plpos.x() << " " << plpos.y() << " error: " << Amg::toString(cov));
870 ATH_MSG_DEBUG(" charge: " << cluster_charge);
871 ATH_MSG_DEBUG(" time: " << cluster_time);
872 ATH_MSG_DEBUG(" status: " << Muon::toString(clustatus));
873 }
874 unsigned int fstrip = results[ire].fstrip;
875 unsigned int lstrip = results[ire].lstrip;
876 std::vector<Identifier> prd_digit_ids_submit;
877 for (unsigned int ids_index = fstrip; ids_index < lstrip + 1; ++ids_index) {
878 if (ids_index >= prd_digit_ids.size()) {
879 ATH_MSG_WARNING("index out of range " << ids_index << " size " << prd_digit_ids.size());
880 continue;
881 }
882 prd_digit_ids_submit.push_back(prd_digit_ids[ids_index]);
883 }
884 unsigned int nstrip = prd_digit_ids_submit.size();
885 ATH_MSG_DEBUG(" size: " << nstrip << " " << sfits.size());
886 ATH_MSG_DEBUG(" all size: " << strips.size() << " " << allStripfits.size());
887
888 // allStripfits.push_back(res);
889
890 CscPrepData* pclus = new CscPrepData(cluster_id,
891 cluster_hash,
892 plpos,
893 prd_digit_ids_submit,
894 cov,
895 pro,
896 int(cluster_charge + 0.5),
897 cluster_time,
898 clustatus,
899 timeStatus);
900 pclus->setHashAndIndex(newCollection->identifyHash(),
901 newCollection->size());
902
903 newCollection->push_back(pclus);
904 }
905 } // end loop over clusters
906
907 return 0;
908}
909
910//******************************************************************************
Scalar phi() const
phi method
#define ATH_CHECK_RECOVERABLE
Evaluate an expression and check for errors.
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
double charge(const T &p)
Definition AtlasPID.h:997
std::pair< std::vector< unsigned int >, bool > res
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
bool msgLvl(const MSG::Level lvl) const
StatusCode getClusters(std::vector< IdentifierHash > &idVect, std::vector< IdentifierHash > &selectedIdVect, Muon::CscPrepDataContainer *object)
ToolHandle< ICscClusterFitter > m_pfitter_def
SG::ReadCondHandleKey< MuonGM::MuonDetectorManager > m_DetectorManagerKey
retrieve MuonDetectorManager from the conditions store
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
StatusCode initialize()
AlgTool InterfaceID.
int make_clusters(bool measphi, const std::vector< const Muon::CscStripPrepData * > &strips, Muon::CscPrepDataCollection *&collection)
ToolHandle< ICscClusterFitter > m_pfitter_prec
ToolHandle< ICscClusterFitter > m_pfitter_split
CscThresholdClusterBuilderTool(const std::string &type, const std::string &aname, const IInterface *)
SG::ReadHandleKey< Muon::CscStripPrepDataContainer > m_digit_key
ToolHandle< ICscStripFitter > m_pstrip_fitter
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
value_type push_back(value_type pElem)
const_iterator end() const noexcept
const_iterator begin() const noexcept
size_type size() const noexcept
ICscStripFitter::Result StripFit
std::vector< StripFit > StripFitList
const_iterator end() const
return const_iterator for end of container
virtual const T * indexFindPtr(IdentifierHash hashId) const override final
return pointer on the found entry or null if out of range using hashed index - fast version,...
virtual StatusCode addCollection(const T *coll, IdentifierHash hashId) override final
insert collection into container with id hash if IDC should not take ownership of collection,...
const_iterator begin() const
return const_iterator for first entry
This is a "hash" representation of an Identifier.
Amg::Vector3D nominalLocalClusterPos(int eta, int wireLayer, int measPhi, double x0) const
ignores internal alignment parameters, hence gives generally incorrect answer (local here is the stat...
int maxNumberOfStrips(int measuresPhi) const
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
const CscReadoutElement * getCscReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
Class representing clusters from the CSC.
Definition CscPrepData.h:39
Class representing the raw data of one CSC strip (for clusters look at Muon::CscPrepData).
virtual const IdentifierHash collectionHash() const final
returns the IdentifierHash corresponding to the channel.
virtual Identifier identify() const override final
virtual void setIdentifier(Identifier id)
virtual IdentifierHash identifyHash() const override final
const_pointer_type cptr()
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Identifier identify() const
return the identifier
void setHashAndIndex(unsigned short collHash, unsigned short objIndex)
TEMP for testing: might make some classes friends later ...
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
MuonPrepDataCollection< CscPrepData > CscPrepDataCollection
MuonPrepDataCollection< CscStripPrepData > CscStripPrepDataCollection
MuonPrepDataContainerT< CscStripPrepData > CscStripPrepDataContainer
std::string toString(CscStripStatus cstat)
Return a string description of a CSC cluster status flag.
@ CscStrStatDead
@ CscStrStatHot
CscClusterStatus
Enum to represent the cluster status - see the specific enum values for more details.
@ CscStatusSimple
Cluster with non-precision fit.
@ CscStatusUndefined
Undefined, should not happen, most likely indicates a problem.
MuonPrepDataContainerT< CscPrepData > CscPrepDataContainer
CscTimeStatus
Enum to represent the cluster time measurement status - see the specific enum values for more details...