ATLAS Offline Software
Loading...
Searching...
No Matches
GepPi0Alg.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/*
6 This algorithm creates clusters from CaloCells, and writes them out
7 as Caloclusters. The clustering strategy is carried out by helper objects.
8 The strategy used is chosen according to string set at configure time. *
9*/
10
11#include "./GepPi0Alg.h"
13
14#include <algorithm>
15#include <queue>
16#include <regex>
17#include <sstream>
18#include <fstream>
19#include <stdexcept>
20#include <queue>
21#include <cmath>
22
23GepPi0Alg::GepPi0Alg(const std::string& name, ISvcLocator* pSvcLocator ) :
24 AthReentrantAlgorithm(name, pSvcLocator){
25}
26
27
29 ATH_MSG_INFO ("Initializing " << name());
30
31 ATH_CHECK(m_totalNoiseKey.initialize());
32 ATH_CHECK(m_caloMgrKey.initialize());
33 CHECK(m_allCaloCellsKey.initialize());
34
35 CHECK(m_cellsProducer.retrieve());
36
37 CHECK(detStore()->retrieve (m_calocell_id, "CaloCell_ID"));
38
39 return StatusCode::SUCCESS;
40}
41
42
43StatusCode GepPi0Alg::execute(const EventContext& ctx) const {
44 // Read in a CaloCell container. Ask producers to create
45 // vectors of CaloCells to be examined.
46
47 ATH_MSG_DEBUG ("Executing " << name());
48
49 // obtain all LAREM CaloCells, then those in EMB1
50 auto h_allCaloCells = SG::makeHandle(m_allCaloCellsKey, ctx);
51 CHECK(h_allCaloCells.isValid());
52
53 const auto & allCaloCells = *h_allCaloCells;
54
55
56
57 // obatain LAREM CaloCells
58 if(! allCaloCells.hasCalo(m_calocell_id->LAREM)){
59 ATH_MSG_ERROR("CaloCellCollection does not contain LAREM cells");
60 return StatusCode::FAILURE;
61 }
62
63 auto cellbegin = allCaloCells.beginConstCalo(CaloCell_ID::LAREM);
64 auto cellend = allCaloCells.endConstCalo(CaloCell_ID::LAREM);
65 ATH_MSG_DEBUG ("Size from SubCalo Iters " << std::distance(cellbegin,
66 cellend));
67
68 std::vector<const CaloCell*>
69 laremCells(allCaloCells.beginConstCalo(CaloCell_ID::LAREM),
70 allCaloCells.endConstCalo(CaloCell_ID::LAREM));
71
72 // Simple checks on the LAREM cell hashes. Will use laremCells vector to
73 // obtain CaloCells goven their hashes.
74 auto front_idhash = m_calocell_id->calo_cell_hash(laremCells.front()->ID());
75 auto back_idhash = m_calocell_id->calo_cell_hash(laremCells.back()->ID());
76
77 // LAREM cell hashes go from 0-173311. check that this is the case
78 // and thar the cells are in hash oeder to allow for indexing.
79
80 constexpr unsigned int LAREMHASH_LO{0};
81
82 if (front_idhash != LAREMHASH_LO) {
83 ATH_MSG_ERROR("front LARM identifier hash != 0, is " << front_idhash);
84 return StatusCode::FAILURE;
85 }
86
87 constexpr unsigned int LAREMHASH_HI{173311};
88
89 if (back_idhash != LAREMHASH_HI) {
90 ATH_MSG_ERROR("back LARM identifier hash != 173311, is " << back_idhash);
91 return StatusCode::FAILURE;
92 }
93
94 if(!std::is_sorted(laremCells.begin(),
95 laremCells.end(),
96 [&cc_id=m_calocell_id](const auto& l, const auto& r) {
97 return
98 cc_id->calo_cell_hash(l->ID()) <
99 cc_id->calo_cell_hash(r->ID());
100 })){
101
102 ATH_MSG_ERROR("LARM CaloCells are not sorted by identifier hash");
103 return StatusCode::FAILURE;
104 }
105
106
107 ATH_MSG_DEBUG("LAREM front, back, diff idhash v size " <<
108 front_idhash << " " <<
109 back_idhash << " " <<
110 back_idhash-front_idhash << " " <<
111 laremCells.size()
112 );
113
114
115 // Now select the cells in the EMB1 sampling layer from laremCells.
116 std::vector<const CaloCell*> allEMB1Cells;
117
118 auto EMB1Selector = [&calocell_id=m_calocell_id](const auto& cell) {
119 auto ha = calocell_id->calo_cell_hash(cell->ID());
120 return calocell_id->calo_sample(ha) == CaloCell_Base_ID::EMB1;
121 };
122
123 std::copy_if(allCaloCells.beginConstCalo(CaloCell_ID::LAREM),
124 allCaloCells.endConstCalo(CaloCell_ID::LAREM),
125 std::back_inserter(allEMB1Cells),
126 EMB1Selector);
127
128
130 if (!totalNoiseHdl.isValid()) {return StatusCode::FAILURE;}
131 const CaloNoise* totalNoiseCDO = *totalNoiseHdl;
132
133
134 // ask tool for emb1CellVecs. The length of emb1CellVecs varies according
135 // to the concrete tool. Examples: If the tool obtains all cells, then the
136 // length of calCellsVecs is 1. If the tool obtains CellCollections
137 // from clusters, then the number of vectors will be equal to the
138 // number of clusters.
139
140 std::vector<std::vector<const CaloCell*>> emb1CellVecs;
141
142 CHECK(m_cellsProducer->cells(emb1CellVecs, ctx));
143
144 // check cells in the EMB1 layer
145
146 for (const auto& cvec : emb1CellVecs) {
147 if (std::find_if_not(cvec.cbegin(),
148 cvec.cend(),
149 EMB1Selector) != cvec.cend()){
150 ATH_MSG_ERROR("cell is not in EMB1 ");
151 return StatusCode::FAILURE;
152 }
153 }
154
155 // one seed cell per emb1Cell collection
156 std::vector<const CaloCell*> seeds(emb1CellVecs.size());
157
158 auto signif = [&totalNoiseCDO,
159 &cut=m_seed_signifcut](const auto& c) -> float {
160 float noise = totalNoiseCDO->getNoise(c->ID(),
161 c->gain());
162 auto sfc = c->e()/noise;
163 return sfc < cut ? 0.:sfc;
164 };
165
166 auto findSeed = [&signif](const auto& cellVec) -> const CaloCell* {
167 return *std::max_element(cellVec.cbegin(),
168 cellVec.cend(),
169 [&signif](const auto& c1,
170 const auto& c2) {
171 return signif(c1) < signif(c2);});};
172
173
174 for (const auto& v: emb1CellVecs) {
175 ATH_MSG_DEBUG("Looking for seed in " << v.size() << " cells");
176 }
177
178 std::transform(emb1CellVecs.cbegin(),
179 emb1CellVecs.cend(),
180 seeds.begin(),
181 findSeed);
182
183 std::size_t iseed{0};
184 for(const auto& seed : seeds) {
185
186 ATH_MSG_DEBUG("seed: eta "<< seed->eta()
187 << " phi " << seed->phi()
188 << " significance "<< signif(seed)
189 );
190
192 caloMgrHandle{m_caloMgrKey, ctx};
193
194 ATH_CHECK(caloMgrHandle.isValid());
195 const CaloDetDescrManager* caloMgr = *caloMgrHandle;
196
197 // run the requested algorithms
198 for (const auto& strategy : m_strategies) {
199 if (strategy == "TWINPEAKS") {
200 try {
202 laremCells,
203 allEMB1Cells,
204 iseed,
205 totalNoiseCDO,
206 caloMgr));
207 } catch (std::runtime_error& e) {
208 ATH_MSG_ERROR("Error running twin peaks - " << e.what());
209 return StatusCode::FAILURE;
210 }
211 } else if (strategy == "SORT") {
212 CHECK(sort_strategy(seed,
213 laremCells,
214 allEMB1Cells,
215 iseed,
216 totalNoiseCDO,
217 caloMgr));
218 } else if (strategy == "CRAWL") {
219 try {
221 laremCells,
222 allEMB1Cells,
223 iseed,
224 totalNoiseCDO,
225 caloMgr));
226
227 } catch (std::runtime_error& e) {
228 ATH_MSG_ERROR("Error running crawl: " << e.what());
229 return StatusCode::FAILURE;
230 }
231 } else {
232 ATH_MSG_ERROR ("Unknown pi0 strategy " << strategy);
233 return StatusCode::FAILURE;
234 }
235 }
236 ++iseed;
237 }
238 ++m_id;
239 return StatusCode::SUCCESS;
240}
241
242
243StatusCode
245 const std::vector<const CaloCell*>& laremCells,
246 const std::vector<const CaloCell*>& allEMB1Cells,
247 std::size_t iseed,
248 const CaloNoise* totalNoiseCDO,
249 const CaloDetDescrManager* caloMgr) const {
250
251 // look for a local maximum in a neighborhood
252 // the siginicance (e/noise) of a maximum must be over a threshold
253 // (for now, set to 2.0)
254 ATH_MSG_DEBUG("twin peaks - start");
255
256
257 if (!seed) {return StatusCode::SUCCESS;}
258 if (allEMB1Cells.empty()) {return StatusCode::SUCCESS;}
259
260
261 // find the neighborhood as a collection of Identifiers
262 std::vector<const CaloCell*> neigh_cells;
263 CHECK(neighborhood(seed, laremCells, neigh_cells, caloMgr));
264
265
266
267 ATH_MSG_DEBUG("twin peaks - neighborhood cells size " << neigh_cells.size()
268 << " input cell collection size " << allEMB1Cells.size());
269
270
271 auto signif = [&totalNoiseCDO](const auto& cell){
272 return cell->e()/totalNoiseCDO->getNoise(cell->ID(), cell->gain());
273 };
274
275 // apply a cut on the signiificance
276 auto new_end = std::partition(neigh_cells.begin(),
277 neigh_cells.end(),
278 [&signif,
279 &signif_cut=m_tp_signifcut](const auto& ncell){
280 return signif(ncell) > signif_cut;
281 });
282
283 neigh_cells.resize(new_end - neigh_cells.begin());
284
285 ATH_MSG_DEBUG("twin peaks - neighborhood size after signif cut: "
286 << neigh_cells.size());
287
288
289 // ---------
290 // create a lambda to look for significant cells in the neighborhood
291 // which are adjacent to a choosen cell (center_cell).
292 auto is_local_max = [neigh_cells, // copy
293 &cc_id=m_calocell_id,
294 &signif](const auto& center_cell) mutable {
295
296 // obtain the hashes of the cells adjacent to center_cell.
297 // some of these will be in the neighborhood. For cells
298 // at the edge of the neighborhood, there may be
299 // adjacent cells not in the neighborhood. For now,
300 // such extra-neighborhood cells will be ignored.
301
302 std::vector<IdentifierHash> adj_hashes;
303 auto rc = cc_id->get_neighbours(cc_id->calo_cell_hash(center_cell->ID()),
305 adj_hashes);
306 if (rc != 0) {
307 throw std::runtime_error("twin peaks - error obtaining cell neighbors");
308 }
309
310 // obtain the identifiers of cells immediately adjacent to center_cell
311 std::vector<Identifier> adj_idents;;
312 std::transform(adj_hashes.cbegin(),
313 adj_hashes.cend(),
314 std::back_inserter(adj_idents),
315 [&cc_id](const auto& hash){
316 return cc_id->cell_id(hash);
317 });
318
319 // obtain neighborhood cells immediately adjacent to center_cell
320
321 auto id_cell_match = [&adj_idents](const CaloCell* n_cell)->bool {
322 return std::find(adj_idents.begin(),
323 adj_idents.end(),
324 n_cell->ID()) != adj_idents.end();};
325
326 auto adj_neigh_cell_end = std::partition(neigh_cells.begin(),
327 neigh_cells.end(),
328 id_cell_match);
329
330 for (auto iter = neigh_cells.begin();
331 iter != adj_neigh_cell_end;
332 ++iter) {
333 if (signif(*iter) > signif(center_cell)) {return false;}
334 }
335
336 return true;
337 };
338
339
340 auto peaks_end = std::partition(neigh_cells.begin(),
341 neigh_cells.end(),
342 std::move(is_local_max));
343
344
345 auto n_peaks = peaks_end - neigh_cells.begin();
346 ATH_MSG_DEBUG("twin peaks - number of local maxima " << n_peaks);
347
348 auto n_peaks_noseed = n_peaks;
349 if (std::find(neigh_cells.begin(), peaks_end, seed) != peaks_end){--n_peaks_noseed;}
350 ATH_MSG_DEBUG("twin peaks - number of local maxima ommiting seed " << n_peaks_noseed);
351
352 ATH_MSG_DEBUG("twin peaks - seed eta " << seed->eta()
353 << " phi " << seed->phi()
354 << " signif " <<signif(seed));
355 for (auto iter = neigh_cells.begin(); iter != peaks_end; ++iter) {
356 ATH_MSG_DEBUG(" twin peaks - peak eta " << (*iter)->eta()
357 << " phi " << (*iter)->phi()
358 << " signif " <<signif(*iter));
359
360 ATH_MSG_DEBUG(" twin peaks - distance from seed deta "
361 << seed->eta() - (*iter)->eta() << " dphi "
362 << seed->phi() - (*iter)->phi());
363 }
364
365 ATH_MSG_DEBUG("twin peaks: neighborhood size after signif cut "
366 << neigh_cells.size());
367
368
369 for (const auto& c: neigh_cells) {
370 if (!c) {throw std::runtime_error("Neighbor pointer is nullptr");}
371
372
373 ATH_MSG_DEBUG("twin peaks - neigh cell eta " << c->eta()
374 << " phi " << c->phi()
375 << " signif " << signif(c));
376 }
377
378
379
380 if (m_dump) {
381
382 std::vector<const CaloCell*> peaks_cells(neigh_cells.begin(), peaks_end);
383
384 std::vector<double> peaks_signif;
385 std::transform(neigh_cells.begin(),
386 peaks_end,
387 std::back_inserter(peaks_signif),
388 signif);
389
390 CHECK(dump_twinpeaks(iseed,
391 seed,
392 signif(seed),
393 neigh_cells,
394 peaks_cells,
395 peaks_signif));
396 }
397
398 ATH_MSG_DEBUG("twin peaks - finished");
399
400 return StatusCode::SUCCESS;
401}
402
403
404StatusCode
406 const std::vector<const CaloCell*>& laremCells,
407 const std::vector<const CaloCell*>& allEMB1Cells,
408 std::size_t iseed,
409 const CaloNoise*,
410 const CaloDetDescrManager* caloMgr) const {
411
412 if (!seed) {return StatusCode::SUCCESS;}
413 if (allEMB1Cells.empty()) {return StatusCode::SUCCESS;}
414
415 std::vector<const CaloCell*> neigh_cells;
416 CHECK(neighborhood(seed, laremCells, neigh_cells, caloMgr));
417
418 ATH_MSG_DEBUG("sort_strategy seed idx " << iseed <<
419 "nbhd size :" << neigh_cells.size());
420
421
422 return StatusCode::SUCCESS;
423}
424
425StatusCode
427 const std::vector<const CaloCell*>& laremCells,
428 const std::vector<const CaloCell*>& allEMB1Cells,
429 std::size_t iseed,
430 const CaloNoise* totalNoiseCDO,
431 const CaloDetDescrManager* caloMgr) const {
432
433 if (!seed) {return StatusCode::SUCCESS;}
434 if (allEMB1Cells.empty()) {return StatusCode::SUCCESS;}
435
436
437 // path_str is a string composed of '0' and '1' characters.
438 // '0' indicates an energy decreases
439 // '1' indicates the energy increases along the path.
440
441 // a path is calculated for a number of contiguous eta steps.
442 // for each eta value, a path is formed in the two phi directions.
443 //
444 // The first step is to determine the CaloCell hashes along
445 // the paths, starting from the location of the seed cell.
446
447 ATH_MSG_DEBUG("crawl: start");
448 ATH_MSG_DEBUG("crawl - seed eta " << seed->eta()
449 << " phi " << seed->phi());
450
451 std::vector<std::string> paths(2*m_er_neta +1);
452
453 auto seed_hash = m_calocell_id->calo_cell_hash(seed->ID());
454
455 std::vector<IdentifierHash> phi_starts;
456
457 // start point for +- phi paths about the seed eta value
458 phi_starts.push_back(seed_hash);
459
460
461 std::vector<LArNeighbours::neighbourOption>
463
464 // start point for +- phi paths above and below the seed eta
465
466 for (const auto& dir : dirs) {
467 auto cur_hash = seed_hash;
468 for (int i = 0; i < m_er_neta; ++i){
469 std::vector<IdentifierHash> v_adj;
470 int rc = m_calocell_id->get_neighbours(cur_hash,
471 dir,
472 v_adj);
473 if (rc != 0) {break;} // out of bounds
474
475 if (v_adj.size() != 1) {
476 // this happens when the the cells no longer form an regular
477 // array. Emprically: at around eta = +- 1.4, the phi spacing
478 // becomes small.
479 // The eta of these cells are almost, but not exactly the same.
480 // The get_neighbours returns multiple cell identifiers in this case.
481 //
482 // When this happens, issue a warning, and break of search in this
483 // eta direction for cells to start the phi crawl.
484 for (const auto& ha : v_adj) {
485 const auto *dde = caloMgr->get_element(m_calocell_id->cell_id(ha));
486 ATH_MSG_DEBUG("cell eta " << dde-> eta() << " phi " << dde->phi() <<
487 " z " << dde->z());
488 }
489 ATH_MSG_WARNING("unexpected number of identifier hashes: "
490 << v_adj.size());
491
492 break;
493 }
494
495 cur_hash = v_adj[0];
496 phi_starts.push_back(cur_hash);
497 }
498 }
499
500 ATH_MSG_DEBUG("crawl - number of 1-dim path start points "
501 << phi_starts.size());
502 for (const auto& h: phi_starts) {
503 auto eta = caloMgr->get_element(m_calocell_id->cell_id(h))->eta();
504 ATH_MSG_DEBUG ("crawl - starting etas " << h << " eta " << eta);
505 }
506
507 std::vector<std::vector<IdentifierHash>> paths_hash;
510
511 for (const auto& dir : dirs){
512
513 auto calc_phihashes = [&dir,
514 &cc_id=m_calocell_id,
515 &nphi=m_er_nphi](auto hash){ //hash: pass by value
516 std::vector<IdentifierHash> path;
517 std::vector<IdentifierHash> adjacent;
518 path.push_back(hash);
519 for (int i = 0; i<nphi; ++i) {
520
521 int rc = cc_id->get_neighbours(hash, dir, adjacent);
522 if (rc != 0) {break;} // out of bounds
523 auto size = adjacent.size();
524 if (size != 1) {
525 throw std::runtime_error("unexpected number of identifier hashes: " + std::to_string(size));
526 }
527
528 hash = adjacent[0];
529 path.push_back(hash);
530
531 }
532 return path;
533 };
534
535 std::transform(phi_starts.cbegin(),
536 phi_starts.cend(),
537 std::back_inserter(paths_hash),
538 std::move(calc_phihashes));
539 };
540
541 ATH_MSG_DEBUG("crawl - number of 1-dim paths (hashes) "
542 << paths_hash.size());
543
544 // step 2 - obtain the paths in terms of CaloCells
545 // std::vector<std::vector<const CaloCell*>> paths_cell;
546 CellVectors paths_cell;
547 paths_cell.reserve(paths_hash.size());
548
549
550 for (const auto& p_h : paths_hash) {
551 std::vector<const CaloCell*> path;
552 path.reserve(p_h.size());
553 std::transform(p_h.cbegin(), p_h.cend(),
554 std::back_inserter(path),
555 [&laremCells](const auto& hash){
556 return laremCells.at(hash);});
557 paths_cell.push_back(std::move(path));
558 }
559
560
561
562 // now have paths of cells.
563 // step 3: create strings of energy up-down patterns
564
565
566 auto signif = [&totalNoiseCDO,
567 &signif_min = m_crawl_signifcut](const auto& cell){
568 auto e = cell->e();
569 if (e <= 0){return 0.;}
570 auto signif = cell->e()/totalNoiseCDO->getNoise(cell->ID(), cell->gain());
571 return signif < signif_min ? 0:signif;
572 };
573
574
575 // std::vector<std::vector<float>> paths_signif;
576 PathsSignif paths_signif;
577 paths_signif.reserve(paths_cell.size());
578
579 // should probably set signif to 0 if below a threhold (eg 2.)
580 for (const auto& p_c : paths_cell) {
581 std::vector<float> path_signif;
582 std::transform(p_c.cbegin(),
583 p_c.cend(),
584 std::back_inserter(path_signif),
585 signif);
586 paths_signif.push_back(std::move(path_signif));
587 }
588
589 for (const auto& p_s: paths_signif) {
590 std::stringstream ss;
591 ss <<"crawl - path signf ";
592 for (const auto& s : p_s) {
593 ss << std::setw(7) << std::setprecision(3)<< s << " ";
594 }
595 ATH_MSG_DEBUG (ss.str());
596 }
597
598
599 std::vector<std::string> paths_pat;
600 paths_pat.reserve(paths_signif.size());
601
602 for (const auto& p_s: paths_signif) {
603 std::string pat{"0"}; // padding to keep the string size as path size
604 if (!p_s.empty()) {
605 for (std::size_t i = 1; i != p_s.size(); ++i) {
606
607 if (p_s[i] > p_s[i-1]) {
608 pat += '1';
609 } else {
610 pat += '0';
611 }
612 }
613
614 paths_pat.push_back(std::move(pat));
615 }
616 }
617
618
619 ATH_MSG_DEBUG("crawl - no of patterns " << paths_pat.size());
620
621 for(const auto& p: paths_pat) {ATH_MSG_DEBUG("crawl - pattern " << p);}
622
623 std::vector<std::regex> peaks_re{
624 std::regex("01*(1)0"), std::regex("01*(1)$")};
625
626 std::vector<const CaloCell*> peak_cells;
627 std::size_t idx{0};
628
629 for (const auto& s : paths_pat) {
630
631 for (const auto& regex : peaks_re) {
632 std::smatch m;
633 if(std::regex_search(s, m, regex)){
634 auto pos = m.position(1);
635 ATH_MSG_DEBUG("crawl - match at idx " << idx << " pos " << pos);
636 peak_cells.push_back(paths_cell[idx][pos]);
637 break;
638 }
639 }
640 ++idx;
641 }
642
643
644 auto n_peaks = peak_cells.size();
645 ATH_MSG_DEBUG("crawl - number of local maxima " << n_peaks);
646 ATH_MSG_DEBUG("crawl - seed eta " << seed->eta()
647 << " phi " << seed->phi()
648 << " signif " <<signif(seed));
649 for (const auto& pc : peak_cells){
650 ATH_MSG_DEBUG(" crawl - peak eta " << pc->eta()
651 << " phi " << pc->phi()
652 << " signif " <<signif(pc));
653
654 ATH_MSG_DEBUG(" crawl - distance from seed deta "
655 << seed->eta() - pc->eta() << " dphi "
656 << seed->phi() - pc->phi());
657 }
658
659 if (m_dump) {CHECK(dump_crawl(iseed,
660 seed,
661 signif(seed),
662 paths_cell,
663 paths_signif,
664 paths_pat));}
665
666 ATH_MSG_DEBUG("crawl: finished");
667
668 return StatusCode::SUCCESS;
669}
670
671StatusCode
673 const CaloCell* seed,
674 float seed_signif,
675 const CellVectors& paths_cell,
676 const std::vector<std::vector<float>>& signifs,
677 const std::vector<std::string>& paths_pat) const {
678 std::stringstream ss;
679 ss << "crawl. cell source " << i << '\n';
680 ss << "seed " << seed->eta() << " " << seed->phi() << " "
681 << seed->e() << " " << seed_signif << '\n';
682 ss << "path etas:\n";
683 for (const auto& path: paths_cell) {
684 for (const auto& c : path){
685 ss << c->eta() << " ";
686 }
687 ss << '\n';
688 }
689 ss << "path phis:\n";
690 for (const auto& path: paths_cell) {
691 for (const auto& c : path){
692 ss << c->phi() << " ";
693 }
694 ss << '\n';
695 }
696
697 ss << "path es:\n";
698 for (const auto& path: paths_cell) {
699 for (const auto& c : path){
700 ss << c->e() << " ";
701 }
702 ss << '\n';
703 }
704
705 ss << "path signifs:\n";
706 for (const auto& path: signifs) {
707 for (const auto& sig : path){
708 ss << sig << " ";
709 }
710 ss << '\n';
711 }
712
713 ss << "path patterns:\n";
714 for (const auto& pat: paths_pat) {
715 ss << pat << '\n';
716 }
717
718
719 std::stringstream fn;
720 fn << "crawl_" << m_id << "_" << i << ".txt";
721 std::ofstream out(fn.str());
722 out << ss.str();
723
724 return StatusCode::SUCCESS;
725}
726
727
728StatusCode
730 const CaloCell* seed,
731 double seed_signif,
732 const std::vector<const CaloCell*>& neighborhood,
733 const std::vector<const CaloCell*>& peaks,
734 const std::vector<double>& peak_signifs) const {
735 std::stringstream ss;
736 ss << "twinpeaks. cell source " << i << '\n';
737 ss << "seed " << seed->eta() << " " << seed->phi() << " "
738 << seed->e() << " " << seed_signif << '\n';
739 ss << "neighborhood etas:\n";
740 for (const auto& c: neighborhood) {
741 ss << c->eta() << " ";
742 }
743 ss << '\n';
744
745 ss << "neighborhood phis:\n";
746 for (const auto& c : neighborhood){
747 ss << c->phi() << " ";
748 }
749 ss << '\n';
750
751 ss << "neighborhood es:\n";
752 for (const auto& c : neighborhood){
753 ss << c->e() << " ";
754 }
755 ss << '\n';
756
757 ss << "peak etas:\n";
758 for (const auto& c : peaks){
759 ss << c->eta() << " ";
760 }
761 ss << '\n';
762
763 ss << "peak phis:\n";
764 for (const auto& c : peaks){
765 ss << c->phi() << " ";
766 }
767 ss << '\n';
768
769 ss << "peak es:\n";
770 for (const auto& c : peaks){
771 ss << c->e() << " ";
772 }
773 ss << '\n';
774
775
776 ss << "peak signifs:\n";
777 for (const auto& s : peak_signifs){
778 ss << s << " ";
779 }
780 ss << '\n';
781
782 std::stringstream fn;
783 fn << "twinpeak_" << m_id << "_" << i << ".txt";
784 std::ofstream out(fn.str());
785 out << ss.str();
786
787 return StatusCode::SUCCESS;
788}
789
790
791
792StatusCode
794 const std::vector<const CaloCell*>& laremCells,
795 std::vector<const CaloCell*>& neigh_cells,
796 const CaloDetDescrManager* caloMgr) const {
797
798 // find the cells in the neighborhood od a seed cell. The neighborhood
799 // cells are those within a Euclidean distance in eta-phi of the seed.
800 // The algorithm works by iteratively finding immediately adjacent cells
801 // to cells already established as being in the neighborhood. If these
802 // cells are within range, they are added to the neighborhood
803
804 auto seedID = seed->ID();
805
806 auto seed_eta = seed->eta();
807 auto seed_phi = seed->phi();
808
809 std::queue<Identifier> to_process;
810 to_process.push(seedID);
811
812 auto accept = [&seed_eta, &seed_phi,
813 &calocell_id=m_calocell_id,
814 &neigh_half_eta = m_neigh_half_eta,
815 &neigh_half_phi = m_neigh_half_phi,
816 &caloMgr](const auto& c_id){
817 auto dde = caloMgr->get_element(c_id);
818 auto c_eta = dde->eta();
819 auto c_phi = dde->phi();
820
821 auto hash = calocell_id->calo_cell_hash(c_id);
822 if (calocell_id->calo_sample(hash) != CaloCell_Base_ID::EMB1) {return false;}
823
824 auto deta = seed_eta-c_eta;
825 if( std::abs(deta) > neigh_half_eta) {return false;}
826
827 auto dphi = seed_phi-c_phi;
828 return std::abs(dphi) < neigh_half_phi;
829
830 };
831
832 std::vector<Identifier> mask;
833 auto add_neighbors_to_queue = [&to_process,
834 &cc_id=m_calocell_id,
835 &mask] (const auto& desc) {
836 auto hash = cc_id->calo_cell_hash(desc);
837 std::vector<IdentifierHash> neigh_hashes;
838 int rc = cc_id->get_neighbours(hash,
840 neigh_hashes);
841 if (rc != 0) {
842 return StatusCode::FAILURE;
843 }
844
845 for (const auto& nh :neigh_hashes) {
846 auto cid = cc_id->cell_id(nh);
847 if (std::find(mask.cbegin(), mask.cend(), cid) == mask.cend()) {
848 mask.push_back(cid);
849 to_process.push(cc_id->cell_id(nh));
850 }
851 }
852 return StatusCode::SUCCESS;
853
854 };
855
856 CHECK(add_neighbors_to_queue(seedID));
857 std::vector<Identifier> neigh_idents;
858
859 // iterative procedure:
860 while (!to_process.empty()){
861 const auto& ident = to_process.front();
862 if (accept(ident)){
863 ATH_MSG_DEBUG (" accepting neigh " << ident);
864 const auto *dde = caloMgr->get_element(ident);
865 auto c_eta = dde->eta();
866 auto c_phi = dde->phi();
867 ATH_MSG_DEBUG(" neigh eta: " << c_eta
868 << " phi " << c_phi);
869 neigh_idents.push_back(ident);
870 add_neighbors_to_queue(ident);
871 }
872 to_process.pop();
873 }
874
875 std::sort(neigh_idents.begin(), neigh_idents.end());
876 auto end = std::unique(neigh_idents.begin(), neigh_idents.end());
877 auto it{neigh_idents.begin()};
878
879 for(;it!= end; ++it){
880 neigh_cells.push_back(laremCells.at(m_calocell_id->calo_cell_hash(*it)));
881 }
882 return StatusCode::SUCCESS;
883}
Scalar eta() const
pseudorapidity method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Definition of CaloDetDescrManager.
#define CHECK(...)
Evaluate an expression and check for errors.
static Double_t ss
static Double_t rc
const ServiceHandle< StoreGateSvc > & detStore() const
Header file for AthHistogramAlgorithm.
An algorithm that can be simultaneously executed in multiple threads.
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
const CaloDetDescrElement * get_element(const Identifier &cellId) const
get element by its identifier
This class provides the client interface for accessing the detector description information common to...
float getNoise(const IdentifierHash h, const int gain) const
Accessor by IdentifierHash and gain.
Definition CaloNoise.h:35
Gaudi::Property< int > m_er_neta
Definition GepPi0Alg.h:119
Gaudi::Property< float > m_tp_signifcut
Definition GepPi0Alg.h:113
StatusCode sort_strategy(const CaloCell *seed, const std::vector< const CaloCell * > &laremCells, const std::vector< const CaloCell * > &emb1Cells, std::size_t iseed, const CaloNoise *, const CaloDetDescrManager *) const
StatusCode dump_twinpeaks(std::size_t iseed, const CaloCell *seed, double seed_signif, const std::vector< const CaloCell * > &neighborhood, const std::vector< const CaloCell * > &peaks, const std::vector< double > &peak_signifs) const
StatusCode neighborhood(const CaloCell *, const std::vector< const CaloCell * > &laremCells, std::vector< const CaloCell * > &neighs, const CaloDetDescrManager *) const
StatusCode crawl_strategy(const CaloCell *seed, const std::vector< const CaloCell * > &laremCells, const std::vector< const CaloCell * > &emb1Cells, std::size_t iseed, const CaloNoise *, const CaloDetDescrManager *) const
Gaudi::Property< int > m_er_nphi
Definition GepPi0Alg.h:122
virtual StatusCode initialize() override
Definition GepPi0Alg.cxx:28
StatusCode dump_crawl(std::size_t iseed, const CaloCell *seed, float seed_signif, const CellVectors &, const PathsSignif &, const std::vector< std::string > &paths_pat) const
virtual StatusCode execute(const EventContext &) const override
Definition GepPi0Alg.cxx:43
StatusCode twinpeaks_strategy(const CaloCell *seed, const std::vector< const CaloCell * > &laremCells, const std::vector< const CaloCell * > &emb1Cells, std::size_t iseed, const CaloNoise *, const CaloDetDescrManager *) const
Gaudi::Property< float > m_neigh_half_eta
Definition GepPi0Alg.h:88
Gaudi::Property< float > m_neigh_half_phi
Definition GepPi0Alg.h:94
Gaudi::Property< std::vector< std::string > > m_strategies
Definition GepPi0Alg.h:101
std::vector< std::vector< const CaloCell * > > CellVectors
Definition GepPi0Alg.h:45
Gaudi::Property< bool > m_dump
Definition GepPi0Alg.h:126
SG::ReadHandleKey< CaloCellContainer > m_allCaloCellsKey
Definition GepPi0Alg.h:60
ToolHandle< ICaloCellsProducer > m_cellsProducer
Definition GepPi0Alg.h:64
Gaudi::Property< float > m_seed_signifcut
Definition GepPi0Alg.h:108
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
Definition GepPi0Alg.h:81
SG::ReadCondHandleKey< CaloNoise > m_totalNoiseKey
Definition GepPi0Alg.h:71
Gaudi::Property< float > m_crawl_signifcut
Definition GepPi0Alg.h:116
std::vector< std::vector< float > > PathsSignif
Definition GepPi0Alg.h:46
const CaloCell_ID * m_calocell_id
Definition GepPi0Alg.h:77
GepPi0Alg(const std::string &name, ISvcLocator *pSvcLocator)
Definition GepPi0Alg.cxx:23
std::atomic< size_t > m_id
Definition GepPi0Alg.h:57
int r
Definition globals.cxx:22
std::map< std::string, int > dirs
list of directories to be explicitly included, together with corresponding depths of subdirectories
Definition hcg.cxx:102
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
DataModel_detail::iterator< DVL > unique(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of unique for DataVector/List.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
DataModel_detail::iterator< DVL > partition(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, Predicate pred)
Specialization of partition for DataVector/List.