ATLAS Offline Software
Loading...
Searching...
No Matches
CscThresholdClusterBuilderTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 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 ");
402 stripId.show();
403 }
404
405 if (res.stripStatus == Muon::CscStrStatHot || res.stripStatus == Muon::CscStrStatDead) isBadChannel = true;
406
407 float stripNoise = 0;
408 if (m_noiseOption == rms) {
409 stripNoise = m_cscCalibTool->stripRMS(stripHash);
410 } else if (m_noiseOption == sigma) {
411 stripNoise = m_cscCalibTool->stripNoise(stripHash);
412 } else if (m_noiseOption == f001) { // f001 is rawADC +1
413 stripNoise = m_cscCalibTool->stripF001(stripHash) - m_cscCalibTool->stripPedestal(stripHash);
414 stripNoise /= 3.251;
415 }
416
417 active = res.charge >= m_threshold && res.charge >= m_kFactor * stripNoise;
418 if (isBadChannel) active = false; // Let's remove Bad channel First...
419
420 if (msgLvl(MSG::DEBUG)) {
421 // Log message.
422 ostringstream strlog;
423 strlog << " Strip " << setw(3) << istrip + 1 << ": charge= " << setw(7) << int(res.charge) << " dcharge= " << setw(7)
424 << int(res.dcharge);
425 if (std::fabs(res.time) < 1e8)
426 strlog << " time=" << setw(3) << int(res.time + 0.5);
427 else
428 strlog << " time=OVERFLOW";
429 if (active)
430 strlog << " *";
431 else if (isBadChannel)
432 strlog << " b";
433 else
434 strlog << " .";
435 if (res.status)
436 strlog << " x";
437 else
438 strlog << " o";
439 strlog << " :" << res.status;
440 ATH_MSG_DEBUG(strlog.str());
441 }
442 }
443 allStripfits.push_back(res);
444 astrip.push_back(active);
445 bstrip.push_back(isBadChannel);
446 }
447
449 // Phase II:
450 //
451 // Bad Channel recovery in case of strip above strip being nearby
453
454 // 1. identify strips to recover
455 std::vector<bool> rstrip; // check recover strip
456 bool IsAnyStripRecovered = false;
457 for (unsigned int istrip = 0; istrip < strips.size(); ++istrip) {
458 bool adjacentActive = false;
459 if (bstrip[istrip]) {
460 if (istrip > 0 && astrip[istrip - 1]) adjacentActive = true;
461 if (istrip + 1 < strips.size() && astrip[istrip + 1]) adjacentActive = true;
462 if (adjacentActive) IsAnyStripRecovered = true;
463 }
464 rstrip.push_back(adjacentActive);
465 }
466
467 // 2. make it active if strip to recover is not active
468 if (IsAnyStripRecovered) { // This loop is needed if there is any bad strip recovered because of adjacent active strip
469
470 if (msgLvl(MSG::DEBUG)) {
471 ostringstream checklog1;
472 ostringstream checklog2;
473
474 for (unsigned int istrip = 0; istrip < strips.size(); ++istrip) {
475 if (istrip % 24 == 0) checklog1 << "\n";
476 checklog1 << int(astrip[istrip]) << " ";
477
478 if (!astrip[istrip] && rstrip[istrip]) { // not active but bad strip with adjacent strip active
479 ATH_MSG_DEBUG("**** Strip " << istrip << " is recovered!!");
480 }
481 if (istrip % 24 == 0) checklog2 << "\n";
482 checklog2 << int(astrip[istrip]) << " ";
483 }
484 ATH_MSG_DEBUG("Strip active map before and after");
485 ATH_MSG_DEBUG(checklog1.str());
486 ATH_MSG_DEBUG(checklog2.str());
487 }
488
489 for (unsigned int istrip = 0; istrip < strips.size(); ++istrip) {
490 if (!astrip[istrip] && rstrip[istrip]) { // not active but bad strip with adjacent strip active
491 astrip[istrip] = rstrip[istrip]; // insert true
492 }
493 }
494 }
496 // Phase III:
497 //
498 // Find clusters : save first strip and nstrip
500 vector<unsigned int> strip0s;
501 vector<unsigned int> nstrips;
502
503 // Loop over strips and create clusters.
504 int nstrip = 0;
505 int first_strip = 0; // First strip in the cluster.
506 bool incluster = false;
507 for (unsigned int istrip = 0; istrip < strips.size(); ++istrip) {
508 // If the current strip is not active, skip it.
509 if (!astrip[istrip]) continue;
510 assert(strips[istrip] != 0); // CscStripPrepData* pstrip = strips[istrip];
511
512 if (!incluster) {
513 incluster = true;
514 nstrip = 0;
515 first_strip = istrip;
516 }
517 ++nstrip;
518
519 // If this is not the last strip in the plane, and the next
520 // strip is active, add the next strip to the cluster.
521 if (istrip != maxstrip - 1 && astrip[istrip + 1]) continue;
522
523 // Recover narrow cluster
524 if (!measphi && nstrip < 3) {
525 bool collectLeftStrip = false;
526 bool collectRightStrip = false;
527
528 if (nstrip == 1) {
529 if (int(istrip) >= nstrip // left adjacent strip should be inside of CSC chamber >0
530 && istrip + 1 < maxstrip // the other side strip should be available < 192
531 && (allStripfits[istrip - 1].charge > 0.1 && allStripfits[istrip + 1].charge > 0.1) // charge should be positive
532 && strips[istrip - 1] && strips[istrip + 1]) { // both adjacent strip identifier should exist
533 collectLeftStrip = true;
534 collectRightStrip = true;
535 }
536 } else if (nstrip == 2) {
537 if (allStripfits[istrip - 1].charge > allStripfits[istrip].charge) { // In case of left strip not fired
538 if (int(istrip) >= nstrip // nstrip 2
539 && allStripfits[istrip - 2].charge > 0.1 // charge should be positive
540 && strips[istrip - 2]) // left strip Identifier should exist
541 collectLeftStrip = true;
542 } else { // In case of right strip not fired
543 if (istrip + 1 < maxstrip &&
544 allStripfits[istrip + 1].charge > 0.1 // charge should be positive if 0, then 0.341E-134 will enter
545 && strips[istrip + 1]) // right strip Identifier should exist
546 collectRightStrip = true;
547 }
548 }
549
550 if (collectLeftStrip) {
551 first_strip = first_strip - 1;
552 nstrip += 1;
553 }
554 if (collectRightStrip) { nstrip += 1; }
555
556 if (msgLvl(MSG::DEBUG)) {
557 // Log message.
558 ostringstream narrowlog;
559 narrowlog << " ** narrow Clusters " << first_strip + 1 << " " << nstrip << " L:R " << collectLeftStrip << " "
560 << collectRightStrip;
561 for (int i = 0; i < nstrip; ++i) { narrowlog << " " << allStripfits[first_strip + i].charge; }
562 for (int i = 0; i < nstrip; ++i) { narrowlog << " " << strips[first_strip + i]; }
563 ATH_MSG_DEBUG(narrowlog.str());
564 }
565 } // Only for eta plane nstrip <3
566
567 strip0s.push_back(first_strip);
568 nstrips.push_back(nstrip);
569
570 // Reset incluster.
571 incluster = false;
572 }
573
575 // Phase IV:
576 //
577 // Merge narrow cluster into adjacent cluster if any exists.
578 // Only for eta strips...
580 vector<unsigned int> newStrip0s;
581 vector<unsigned int> newNstrips;
582
583 int nMerged = 0; // the difference b/w old Nclu and new Nclu
584 for (unsigned int icl = 0; icl < nstrips.size(); ++icl) {
585 unsigned int nstrip = nstrips[icl];
586 unsigned int strip0 = strip0s[icl];
587
588 ATH_MSG_VERBOSE(" " << icl << "th cluster merger " << strip0 << " " << nstrip);
589
590 //#### if you find narrow cluster
591 if (!measphi) {
592 if (nstrip < 3) {
593 // at least one cluster before to check left cluster and continuous
594 if (icl > 0 && (strip0 == strip0s[icl - 1] + nstrips[icl - 1])) {
595 unsigned int newStrip0 = strip0s[icl - 1];
596 unsigned int newNstrip = nstrips[icl - 1] + nstrip;
597
598 ATH_MSG_DEBUG(" " << icl << " ** narrow Cluster merger Type I" << newStrip0 << " " << newNstrip);
599
600 newStrip0s[icl - 1 - nMerged] = newStrip0;
601 newNstrips[icl - 1 - nMerged] = newNstrip;
602 ++nMerged;
603 continue;
604 }
605 // at least one cluster after to check right cluster and continuous
606 if (icl + 1 < nstrips.size() && (strip0 + nstrip == strip0s[icl + 1])) {
607 unsigned int newStrip0 = strip0;
608 unsigned int newNstrip = nstrip + nstrips[icl + 1];
609
610 ATH_MSG_DEBUG(" " << icl << " ** narrow Cluster merger Type II" << newStrip0 << " " << newNstrip);
611
612 newStrip0s.push_back(newStrip0);
613 newNstrips.push_back(newNstrip);
614
615 icl += 1;
616 ++nMerged;
617 continue;
618 }
619 }
620 } // !measphi
621 // if nstrip >2 OR
622 // still narrow strip then just keep it...
623 newStrip0s.push_back(strip0);
624 newNstrips.push_back(nstrip);
625 } // for
626
627 if (strip0s.size() != newStrip0s.size()) {
628 ATH_MSG_DEBUG(" Phase II -> III Merged " << strip0s.size() << ":" << nstrips.size() << " " << newStrip0s.size() << ":"
629 << newNstrips.size());
630 for (unsigned int icl = 0; icl < nstrips.size(); ++icl)
631 ATH_MSG_DEBUG(" *** " << icl << " [" << strip0s[icl] << "," << strip0s[icl] + nstrips[icl] - 1 << "] " << nstrips[icl]);
632 for (unsigned int icl = 0; icl < newNstrips.size(); ++icl)
633 ATH_MSG_DEBUG(" ****** " << icl << " [" << newStrip0s[icl] << "," << newStrip0s[icl] + newNstrips[icl] - 1 << "] "
634 << newNstrips[icl]);
635 }
636
638 // Phase V:
639 //
640 // Using strip0 and nstrip fill up collection
642
644 std::vector<const CscStripPrepData*> clusterStrips;
645 clusterStrips.reserve(50);
646 std::vector<Identifier> prd_digit_ids;
647 prd_digit_ids.reserve(50);
648
649 for (unsigned int icl = 0; icl < newNstrips.size(); ++icl) { // for each cluster
650
651 ATH_MSG_VERBOSE(" Creating " << icl << "th cluster");
652
653 unsigned int nstrip = newNstrips[icl]; // only used here
654 unsigned int strip0 = newStrip0s[icl]; // only used here
655
656 sfits.clear();
657 clusterStrips.clear();
658 prd_digit_ids.clear();
659
660 for (unsigned int ist = strip0; ist < strip0 + nstrip; ++ist) {
661 const CscStripPrepData* pstrip = strips[ist];
662 const ICscClusterFitter::StripFit& sfit = allStripfits[ist];
663
664 sfits.push_back(sfit);
665 clusterStrips.push_back(pstrip);
666 prd_digit_ids.push_back(pstrip->identify());
667 }
668
669 ATH_MSG_VERBOSE(" ++++++++++++++ nstrip +++++ " << nstrip);
671 if (nstrip < 3 && m_makeNarrowClusterThreeStrips) {
675
676 bool leftToFill = false;
677 bool rightToFill = false;
678 if (nstrip == 1) {
679 leftToFill = true;
680 rightToFill = true;
681 } else {
682 if (sfits[0].charge > sfits[1].charge) {
683 leftToFill = true;
684 } else if (sfits[0].charge < sfits[1].charge) {
685 rightToFill = true;
686 } else {
687 ATH_MSG_DEBUG(" It should be CHECKED!!! ");
688 if (strip0 > 0) {
689 if (strips[strip0 - 1]) {
690 leftToFill = true;
691 } else if (strips[strip0 + 2]) {
692 rightToFill = true;
693 }
694 } else if (strips[strip0 + 2]) {
695 rightToFill = true;
696 }
697 }
698 }
699
700 ATH_MSG_VERBOSE(" strip0 nstrip filling left or right " << strip0 << " " << nstrip << " " << leftToFill << " "
701 << rightToFill);
702 ATH_MSG_VERBOSE(" sfits[0] " << sfits[0].charge);
703 if (nstrip == 2) ATH_MSG_VERBOSE(" sfits[1] " << sfits[1].charge);
704
705 for (unsigned int i = 0; i < allStripfits.size(); ++i) { ATH_MSG_VERBOSE("index " << i << " " << allStripfits[i].charge); }
706
707 if (leftToFill) {
708 // ATH_MSG_DEBUG( " Left to fill " << allStripfits[strip0-1].charge);
709 bool fillTheOtherSide = false;
710 if (strip0 == 0) {
711 fillTheOtherSide = true;
712 } else {
713 if (strips[strip0 - 1] == nullptr) fillTheOtherSide = true;
714 }
715
716 if (strip0 + nstrip >= allStripfits.size()) { fillTheOtherSide = false; }
717
718 if (!fillTheOtherSide) {
719 if (strips[strip0 - 1]) {
720 sfits.insert(sfits.begin(), allStripfits[strip0 - 1]);
721 clusterStrips.insert(clusterStrips.begin(), strips[strip0 - 1]);
722 prd_digit_ids.insert(prd_digit_ids.begin(), strips[strip0 - 1]->identify());
723 strip0--;
724 nstrip = prd_digit_ids.size();
725 }
726 } else {
727 if (strips[strip0 + nstrip]) { // for edge this can happen
728 sfits.push_back(allStripfits[strip0 + nstrip]); // This is the case for example
729 // 12799.6 39183.9 39698
730 clusterStrips.push_back(strips[strip0 + nstrip]);
731 prd_digit_ids.push_back(strips[strip0 + nstrip]->identify());
732 nstrip = prd_digit_ids.size();
733 }
734 }
735 }
736
737 if (rightToFill) {
738 bool fillTheOtherSide = false;
739 if (strip0 + nstrip >= allStripfits.size()) {
740 fillTheOtherSide = true;
741 } else {
742 if (strips[strip0 + nstrip] == nullptr) fillTheOtherSide = true;
743 }
744
745 if (strip0 == 0) { fillTheOtherSide = false; }
746
747 if (!fillTheOtherSide) {
748 if (strips[strip0 + nstrip]) {
749 sfits.push_back(allStripfits[strip0 + nstrip]);
750 clusterStrips.push_back(strips[strip0 + nstrip]);
751 prd_digit_ids.push_back(strips[strip0 + nstrip]->identify());
752 nstrip = prd_digit_ids.size();
753 }
754 } else {
755 if (strips[strip0 - 1]) { // for edge this can happen
756 sfits.insert(sfits.begin(), allStripfits[strip0 - 1]);
757 clusterStrips.insert(clusterStrips.begin(), strips[strip0 - 1]);
758 prd_digit_ids.insert(prd_digit_ids.begin(), strips[strip0 - 1]->identify());
759 strip0--;
760 nstrip = prd_digit_ids.size();
761 }
762 }
763 }
764 }
766
767 int fitresult = 99;
768 std::vector<ICscClusterFitter::Result> results;
769
770 // Precision fit.
771 if (!measphi) {
772 results = m_pfitter_prec->fit(sfits);
773 fitresult = results[0].fitStatus;
774 ATH_MSG_VERBOSE(" Performing precision fit " << m_pfitter_prec << " result return=" << fitresult);
775
776 // in case of multipeak cluster
777 if (fitresult == 6) {
778 results = m_pfitter_split->fit(sfits);
779 fitresult = results[0].fitStatus;
780 for (unsigned int i = 0; i < results.size(); ++i)
781 ATH_MSG_VERBOSE(" Performing split fit with " << m_pfitter_split << " result return=" << results[i].fitStatus);
782 }
783 }
784
785 bool precisionFitFailed = fitresult > 0 && fitresult < 20; // splitclusterFit fail => 19
786 // Default fit for phi and eta failed
787 if (measphi || precisionFitFailed) {
789 CscClusterStatus oldclustatus;
790 if (!measphi) {
791 res = results[0];
792 oldclustatus = res.clusterStatus;
793 } else {
794 oldclustatus = Muon::CscStatusSimple;
795 }
796 results = m_pfitter_def->fit(sfits);
797 if (!results.empty()) {
798 res = results[0];
799 fitresult = results[0].fitStatus;
800 if (msgLvl(MSG::VERBOSE)) {
801 ostringstream deflog;
802 deflog << " Performing default fit with " << m_pfitter_def;
803 if (fitresult) {
804 deflog << " failed: return=" << fitresult;
805 } else {
806 deflog << " succeeded";
807 }
808 ATH_MSG_VERBOSE(deflog.str());
809 }
810 // Keep the status from the first fit if it is defined.
811 if (oldclustatus != Muon::CscStatusUndefined) {
812 res.clusterStatus = oldclustatus;
813 // we want to keep oldcluster status
814 results[0] = res;
815 }
816 }
817 }
818
820 //
821 // Phase V. For multiple results, fill up collection
822 //
824 unsigned int nresults = results.size();
825 for (unsigned int ire = 0; ire < nresults; ++ire) {
826 CscClusterStatus clustatus = results[ire].clusterStatus;
827 Muon::CscTimeStatus timeStatus = results[ire].timeStatus;
828 double pos = results[ire].position;
829 double err = results[ire].dposition;
830 unsigned int id_strip = results[ire].strip; // return peak strip index (unsigned integer)
831 double cluster_charge = results[ire].charge;
832 double cluster_time = results[ire].time;
833 if (clustatus == Muon::CscStatusUndefined) ATH_MSG_DEBUG(" Csc Cluster Status is not defined.");
834
835 if (id_strip >= sfits.size()) {
836 ATH_MSG_WARNING(" Fit size check failed: ");
837 continue;
838 }
839 // Fetch the strip used to identify this cluster.
840 const CscStripPrepData* pstrip_id = nullptr;
841 if (id_strip < clusterStrips.size()) pstrip_id = clusterStrips[id_strip];
842 if (!pstrip_id) {
843 ATH_MSG_WARNING(" Fit ID check failed: ");
844 continue;
845 }
846
847 // Create ATLAS CSC cluster.
848 Identifier cluster_id = pstrip_id->identify();
849 IdentifierHash cluster_hash = pstrip_id->collectionHash();
850 int zsec = m_idHelperSvc->cscIdHelper().stationEta(cluster_id);
851 int wlay = m_idHelperSvc->cscIdHelper().wireLayer(cluster_id);
852 // This local position is in the muon (not tracking) coordinate system.
853 // retrieve MuonDetectorManager from the conditions store
855 const MuonGM::MuonDetectorManager* MuonDetMgr = DetectorManagerHandle.cptr();
856 if (MuonDetMgr == nullptr) {
857 ATH_MSG_ERROR("Null pointer to the MuonDetectorManager conditions object");
858 return 0;
859 }
860 const CscReadoutElement* pro = MuonDetMgr->getCscReadoutElement(cluster_id);
861 // Amg::Vector3D local_pos = pro->localClusterPos(zsec, wlay, measphi, pos);
862 Amg::Vector3D localTrk_pos = pro->nominalLocalClusterPos(zsec, wlay, measphi, pos);
863
864 auto cov = Amg::MatrixX(1, 1);
865 (cov)(0, 0) = err * err;
866 Amg::Vector2D plpos(measphi ? localTrk_pos.y() : localTrk_pos.z(), measphi ? localTrk_pos.z() : localTrk_pos.y());
867 if (msgLvl(MSG::DEBUG)) {
868 ATH_MSG_DEBUG(" Cluster parameters: " << nresults);
869 ATH_MSG_DEBUG(" ID strip: " << first_strip + id_strip << "(" << first_strip << ":" << id_strip << ")");
870 ATH_MSG_DEBUG(" local position: " << plpos.x() << " " << plpos.y() << " error: " << Amg::toString(cov));
871 ATH_MSG_DEBUG(" charge: " << cluster_charge);
872 ATH_MSG_DEBUG(" time: " << cluster_time);
873 ATH_MSG_DEBUG(" status: " << Muon::toString(clustatus));
874 }
875 unsigned int fstrip = results[ire].fstrip;
876 unsigned int lstrip = results[ire].lstrip;
877 std::vector<Identifier> prd_digit_ids_submit;
878 for (unsigned int ids_index = fstrip; ids_index < lstrip + 1; ++ids_index) {
879 if (ids_index >= prd_digit_ids.size()) {
880 ATH_MSG_WARNING("index out of range " << ids_index << " size " << prd_digit_ids.size());
881 continue;
882 }
883 prd_digit_ids_submit.push_back(prd_digit_ids[ids_index]);
884 }
885 unsigned int nstrip = prd_digit_ids_submit.size();
886 ATH_MSG_DEBUG(" size: " << nstrip << " " << sfits.size());
887 ATH_MSG_DEBUG(" all size: " << strips.size() << " " << allStripfits.size());
888
889 // allStripfits.push_back(res);
890
891 CscPrepData* pclus = new CscPrepData(cluster_id,
892 cluster_hash,
893 plpos,
894 prd_digit_ids_submit,
895 cov,
896 pro,
897 int(cluster_charge + 0.5),
898 cluster_time,
899 clustatus,
900 timeStatus);
901 pclus->setHashAndIndex(newCollection->identifyHash(),
902 newCollection->size());
903
904 newCollection->push_back(pclus);
905 }
906 } // end loop over clusters
907
908 return 0;
909}
910
911//******************************************************************************
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.
void show() const
Print out in hex form.
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...