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