ATLAS Offline Software
Loading...
Searching...
No Matches
MmIdHelper.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
9#include "IdDict/IdDictMgr.h"
10#include "IdDict/IdDictRegion.h"
12
14
15/*******************************************************************************/
16// Constructor/Destructor
17MmIdHelper::MmIdHelper() : MuonIdHelper("MmIdHelper", "mm") {
18 m_module_hashes.fill(-1);
20}
21/*******************************************************************************/
22// Initialize dictionary
24 int status = 0;
25
26 // Check whether this helper should be reinitialized
27 if (!reinitialize(dict_mgr)) {
28 ATH_MSG_INFO("Request to reinitialize not satisfied - tags have not changed");
29 return (0);
30 } else {
31 ATH_MSG_DEBUG("(Re)initialize ");
32 }
33
34 // init base object
35 if (AtlasDetectorID::initialize_from_dictionary(dict_mgr)) return 1;
36
37 // Register version of the MuonSpectrometer dictionary
38 if (register_dict_tag(dict_mgr, "MuonSpectrometer")) return 1;
39
40 m_dict = dict_mgr.find_dictionary("MuonSpectrometer");
41 if (!m_dict) {
42 ATH_MSG_ERROR(" initialize_from_dict - cannot access MuonSpectrometer dictionary ");
43 return 1;
44 }
45
46 // Initialize some of the field indices
47 if (initLevelsFromDict()) return 1;
48
49 int index = technologyIndex("MM");
50 if (index == -1) {
51 ATH_MSG_DEBUG("initLevelsFromDict - there are no MM entries in the dictionary! ");
52 return 0;
53 }
54
55 const IdDictField* field = m_dict->find_field("mmMultilayer");
56 if (field) {
57 m_DETECTORELEMENT_INDEX = field->index();
58 } else {
59 ATH_MSG_ERROR("initLevelsFromDict - unable to find 'mmMultilayer' field ");
60 return 1;
61 }
62
63 field = m_dict->find_field("mmGasGap");
64 if (field) {
65 m_GASGAP_INDEX = field->index();
66 } else {
67 ATH_MSG_ERROR("initLevelsFromDict - unable to find 'mmGasGap' field ");
68 return 1;
69 }
70
71 field = m_dict->find_field("mmChannel");
72 if (field) {
73 m_CHANNEL_INDEX = field->index();
74 } else {
75 ATH_MSG_ERROR("initLevelsFromDict - unable to find mmChannel' field ");
76 status = 1;
77 }
78
79 // reinitialize the module ndex
81
82 // save an index to the first region of MM
83 const IdDictGroup* mmGroup = m_dict->find_group("mm");
84 if (!mmGroup) {
85 ATH_MSG_ERROR("Cannot find mm group");
86 return 1;
87 } else {
88 m_GROUP_INDEX = mmGroup->region(0).index();
89 }
90
91 const IdDictRegion& region = m_dict->region(m_GROUP_INDEX);
98
99 ATH_MSG_DEBUG(" MicroMegas decode index and bit fields for each level: " << std::endl
100 << " muon " << m_muon_impl.show_to_string() << std::endl
101 << " station " << m_sta_impl.show_to_string() << std::endl
102 << " eta " << m_eta_impl.show_to_string() << std::endl
103 << " phi " << m_phi_impl.show_to_string() << std::endl
104 << " technology " << m_tec_impl.show_to_string() << std::endl
105 << " multilayer " << m_mplet_impl.show_to_string()
106 << std::endl
107 << " gasgap " << m_gap_impl.show_to_string() << std::endl
108 << " channel " << m_cha_impl.show_to_string());
109
110 //
111 // Build multirange for the valid set of identifiers
112 //
113
114 // Find value for the field MuonSpectrometer
115 int muonField = -1;
116 const IdDictDictionary* atlasDict = dict_mgr.find_dictionary("ATLAS");
117 if (atlasDict->get_label_value("subdet", "MuonSpectrometer", muonField)) {
118 ATH_MSG_ERROR("Could not get value for label 'MuonSpectrometer' of field 'subdet' in dictionary " << atlasDict->name());
119 return 1;
120 }
121
122 // Build MultiRange down to "technology" for all (muon) regions
123 ExpandedIdentifier region_id;
124 region_id.add(muonField);
125 Range prefix;
126 MultiRange muon_range = m_dict->build_multirange(region_id, prefix, "technology");
127 if (muon_range.size() > 0) {
128 ATH_MSG_INFO("MultiRange built successfully to Technology: "
129 << "MultiRange size is " << muon_range.size());
130 } else {
131 ATH_MSG_ERROR("Muon MultiRange is empty");
132 return 1;
133 }
134
135 // Build MultiRange down to "detector element" for all mdt regions
136 ExpandedIdentifier detectorElement_region;
137 detectorElement_region.add(muonField);
138 Range detectorElement_prefix;
139 MultiRange muon_detectorElement_range = m_dict->build_multirange(detectorElement_region, detectorElement_prefix, "mmMultilayer");
140 if (muon_detectorElement_range.size() > 0) {
141 ATH_MSG_INFO("MultiRange built successfully to detector element: "
142 << "Multilayer MultiRange size is " << muon_detectorElement_range.size());
143 } else {
144 ATH_MSG_ERROR("Muon MicroMegas detector element MultiRange is empty");
145 return 1;
146 }
147
148 // Build MultiRange down to "channel" for all MM regions
149 ExpandedIdentifier mm_region;
150 mm_region.add(muonField);
151 Range mm_prefix;
152 MultiRange muon_channel_range = m_dict->build_multirange(mm_region, mm_prefix, "mmChannel");
153 if (muon_channel_range.size() > 0) {
154 ATH_MSG_INFO("MultiRange built successfully to channel: "
155 << "MultiRange size is " << muon_channel_range.size());
156 } else {
157 ATH_MSG_ERROR("Muon MultiRange is empty for channels");
158 }
159
160 // build MicroMegas module ranges
161 // Find the regions that have a "technology field" that matches the MM and save them
162 int mmField = -1;
163 status = m_dict->get_label_value("technology", "MM", mmField);
164
165 for (int i = 0; i < (int)muon_range.size(); ++i) {
166 const Range& range = muon_range[i];
167 if (range.fields() > m_TECHNOLOGY_INDEX) {
168 const Range::field& field = range[m_TECHNOLOGY_INDEX];
169 if (field.match((ExpandedIdentifier::element_type)mmField)) {
170 m_full_module_range.add(range);
171 ATH_MSG_DEBUG("field size is " << (int)range.cardinality() << " field index = " << i);
172 }
173 }
174 }
175
176 for (int j = 0; j < (int)muon_detectorElement_range.size(); ++j) {
177 const Range& range = muon_detectorElement_range[j];
178 if (range.fields() > m_TECHNOLOGY_INDEX) {
179 const Range::field& field = range[m_TECHNOLOGY_INDEX];
180 if (field.match((ExpandedIdentifier::element_type)mmField)) {
182 ATH_MSG_DEBUG("detector element field size is " << (int)range.cardinality() << " field index = " << j);
183 }
184 }
185 }
186
187 for (int j = 0; j < (int)muon_channel_range.size(); ++j) {
188 const Range& range = muon_channel_range[j];
189 if (range.fields() > m_TECHNOLOGY_INDEX) {
190 const Range::field& field = range[m_TECHNOLOGY_INDEX];
191 if (field.match((ExpandedIdentifier::element_type)mmField)) {
192 m_full_channel_range.add(range);
193 ATH_MSG_DEBUG("channel field size is " << (int)range.cardinality() << " field index = " << j);
194 }
195 }
196 }
197
198 // test to see that the multi range is not empty
199 if (m_full_module_range.size() == 0) {
200 ATH_MSG_ERROR("MicroMegas MultiRange ID is empty for modules");
201 return 1;
202 }
203
204 // test to see that the detector element multi range is not empty
205 if (m_full_detectorElement_range.size() == 0) {
206 ATH_MSG_ERROR("MicroMegas MultiRange ID is empty for detector elements");
207 return 1;
208 }
209
210 // test to see that the multi range is not empty
211 if (m_full_channel_range.size() == 0) {
212 ATH_MSG_ERROR("MicroMegas MultiRange ID is empty for channels");
213 return 1;
214 }
215
216 // Setup the hash tables for MicroMegas
217 ATH_MSG_INFO("Initializing MicroMegas hash indices ... ");
218 status += init_hashes();
219 status += init_detectorElement_hashes(); // same as module hash
220 status += init_id_to_hashes();
221
222 // Setup hash tables for finding neighbors
223 ATH_MSG_INFO("Initializing MicroMegas hash indices for finding neighbors ... ");
224 status += init_neighbors();
225
226 m_init = true;
227 return (status);
228} // end MmIdHelper::initialize_from_dictionary
229/*******************************************************************************/
230
231inline unsigned int MmIdHelper::moduleHashIdx(const Identifier& id) const{
234 constexpr unsigned int C = s_phiDim;
235 constexpr unsigned int BxC = C*s_etaDim;
236 const int stEta = stationEta(id);
237 return (stationName(id) - m_stationShift)*BxC + (stEta + s_etaDim/2 - (stEta>0))*C + (stationPhi(id) -1);
238}
239inline unsigned int MmIdHelper::detEleHashIdx(const Identifier& id) const{
240 return moduleHashIdx(id) *s_mlDim + (multilayer(id) -1);
241}
242
244 for (const Identifier& id : m_module_vec) m_stationShift = std::min(m_stationShift, 1u* stationName(id));
245 unsigned int hash_max = module_hash_max();
246 for (unsigned int i = 0; i < hash_max; ++i) {
247 const Identifier& id = m_module_vec[i];
248 const unsigned idx = moduleHashIdx(id);
249 if (idx >= m_module_hashes.size() || m_module_hashes[idx] < hash_max){
250 ATH_MSG_FATAL("Failed to assign module hash to "<<show_to_string(id));
251 return 1;
252 }
253 m_module_hashes[idx] = i;
254 }
255
256 hash_max = detectorElement_hash_max();
257 for (unsigned int i = 0; i < hash_max; ++i) {
258 const Identifier& id = m_detectorElement_vec[i];
259 const unsigned idx = detEleHashIdx(id);
260 if (idx >= m_detectorElement_hashes.size() || m_detectorElement_hashes[idx] < hash_max){
261 ATH_MSG_FATAL("Failed to assign detector hash to "<<show_to_string(id));
262 return 1;
263 }
265 }
266 return 0;
267} // end MmIdHelper::init_id_to_hashes()
268/*******************************************************************************/
270 const unsigned int idx = moduleHashIdx(id);
271 if (idx >= m_module_hashes.size()) return 1;
272 hash_id = m_module_hashes[idx];
273 return 0;
274} // end MmIdHelper::get_module_hash
275/*******************************************************************************/
277 const unsigned int idx = detEleHashIdx(id);
278 if (idx >= m_detectorElement_hashes.size()) return 1;
279 hash_id = m_detectorElement_hashes[idx];
280 return 0;
281 // return get_module_hash(id, hash_id);
282}
283/*******************************************************************************/
285 assert(is_mm(channelID));
287 // m_mplet_impl.reset(result);
288 m_gap_impl.reset(result);
289 m_cha_impl.reset(result);
290 return result;
291}
292/*******************************************************************************/
294 Identifier result(moduleID);
296 return result;
297}
299 try {
300 const Identifier result = multilayerID(moduleID, multilayer);
302 return result;
303 } catch (const std::out_of_range&) { isValid = false; }
304 return Identifier{0};
305}
306/*******************************************************************************/
308 int pcbNb = std::abs(stationEta)==1 ? pcb : pcb-5;
309 return (pcbNb-1)*1024+1;
310}
312 int chnl = getFirstPcbChnl(stationEta, pcb);
314}
316 int chnl = getFirstPcbChnl(stationEta, pcb);
318}
319Identifier MmIdHelper::pcbID(const std::string& stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int pcb) const {
320 int chnl = getFirstPcbChnl(stationEta, pcb);
322}
323Identifier MmIdHelper::pcbID(const std::string& stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int pcb, bool& isValid) const {
324 int chnl = getFirstPcbChnl(stationEta, pcb);
326}
327Identifier MmIdHelper::pcbID(const Identifier& channelId, int pcb) const {
328 int chnl = getFirstPcbChnl(stationEta(channelId), pcb);
329 return channelID(channelId, multilayer(channelId), gasGap(channelId), chnl);
330}
331Identifier MmIdHelper::pcbID(const Identifier& channelId, int pcb, bool& isValid) const {
332 int chnl = getFirstPcbChnl(stationEta(channelId), pcb);
333 return channelID(channelId, multilayer(channelId), gasGap(channelId), chnl, isValid);
334}
335Identifier MmIdHelper::pcbID(const Identifier& channelId) const {
336 int chnl = channel(channelId);
337 // PCB counts from 1-8. PCBs 1-5 are in abs(stationEta)==1 and PCBs 6-8 in abs(stationEta)==2
338 // each PCB consists of 1024 readout strips (strip number in athena is counting from 1 therefore chnl -1)
339 int pcb = (chnl-1)/1024+1 + (std::abs(stationEta(channelId))==2 ? 5:0); // int division should round downwards
340 return pcbID(channelId, pcb);
341}
342/*******************************************************************************/
344 int radiusNb = std::abs(stationEta)==1 ? radius : radius-10;
345 return radiusNb*512+1;
346}
348 int chnl = getFirstRadiusChnl(stationEta, radius);
350}
351Identifier MmIdHelper::febID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int radius, bool& isValid) const {
352 int chnl = getFirstRadiusChnl(stationEta, radius);
354}
355Identifier MmIdHelper::febID(const std::string& stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int radius) const {
356 int chnl = getFirstRadiusChnl(stationEta, radius);
358}
359Identifier MmIdHelper::febID(const std::string& stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int radius, bool& isValid) const {
360 int chnl = getFirstRadiusChnl(stationEta, radius);
362}
363Identifier MmIdHelper::febID(const Identifier& channelId, int radius) const {
364 int chnl = getFirstRadiusChnl(stationEta(channelId), radius);
365 return channelID(channelId, multilayer(channelId), gasGap(channelId), chnl);
366}
367Identifier MmIdHelper::febID(const Identifier& channelId, int radius, bool& isValid) const {
368 int chnl = getFirstRadiusChnl(stationEta(channelId), radius);
369 return channelID(channelId, multilayer(channelId), gasGap(channelId), chnl, isValid);
370}
371Identifier MmIdHelper::febID(const Identifier& channelId) const {
372 int chnl = channel(channelId);
373 // radius counts from 0-15. Radii 0-9 are in abs(stationEta)==1 and radii 10-15 in abs(stationEta)==2
374 // each radius consists of 512 readout strips (strip number in athena is counting from 1 therefore chnl -1)
375 int radius = (chnl-1)/512 + (std::abs(stationEta(channelId))==2 ? 10:0); // int division should round downwards
376 return febID(channelId, radius);
377}
378/*******************************************************************************/
379void MmIdHelper::idChannels(const Identifier& id, std::vector<Identifier>& vect) const {
380 vect.clear();
381 Identifier parent = parentID(id);
382 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
383 const Range& range = m_full_channel_range[i];
384 ConstRangeIterator rit(range);
385 for (const auto & expId : rit) {
386 Identifier child;
387 get_id(expId, child);
388 if (parentID(child) == parent) vect.push_back(child);
389 }
390 }
391}
392/*******************************************************************************/
394 int result = -999;
395 for (unsigned int i = 0; i < m_full_module_range.size(); ++i) {
396 const Range& range = m_full_module_range[i];
397 if (range.match(expId)) {
398 const Range::field& eta_field = range[m_ETA_INDEX];
399 if (not eta_field.empty()) {
400 int etamin = eta_field.get_minimum();
401 if (-999 == result) {
402 result = etamin;
403 } else {
404 if (etamin < result) result = etamin;
405 }
406 }
407 }
408 }
409 return (result);
410} // end MmIdHelper::stationEtaMin
411/*******************************************************************************/
413 ExpandedIdentifier expId;
414 IdContext eta_context(expId, 0, m_ETA_INDEX);
415 if (!get_expanded_id(id, expId, &eta_context)) {
416 return stationEtaMin(expId);
417 }
418 return (999); // default
419} // end MmIdHelper::stationEtaMin
420/*******************************************************************************/
422 int result = -999;
423 for (unsigned int i = 0; i < m_full_module_range.size(); ++i) {
424 const Range& range = m_full_module_range[i];
425 if (range.match(expId)) {
426 const Range::field& eta_field = range[m_ETA_INDEX];
427 if (not eta_field.empty()) {
428 int etamax = eta_field.get_maximum();
429 if (result < etamax) result = etamax;
430 }
431 }
432 }
433 return (result);
434} // end MmIdHelper::stationEtaMax
435/*******************************************************************************/
437 ExpandedIdentifier expId;
438 IdContext eta_context(expId, 0, m_ETA_INDEX);
439 if (!get_expanded_id(id, expId, &eta_context)) {
440 return stationEtaMax(expId);
441 }
442 return (-999);
443} // end MmIdHelper::stationEtaMax
444/*******************************************************************************/
446 for (unsigned int i = 0; i < m_full_module_range.size(); ++i) {
447 const Range& range = m_full_module_range[i];
448 if (range.match(expId)) {
449 const Range::field& phi_field = range[m_PHI_INDEX];
450 if (not phi_field.empty()) { return (phi_field.get_minimum()); }
451 }
452 }
453 // Failed to find the min
454 return (999);
455}
456/*******************************************************************************/
458 ExpandedIdentifier expId;
459 IdContext phi_context(expId, 0, m_PHI_INDEX);
460
461 if (!get_expanded_id(id, expId, &phi_context)) {
462 return stationPhiMin(expId);
463 }
464 // Failed to find the min
465 return (999);
466}
467/*******************************************************************************/
469 for (unsigned int i = 0; i < m_full_module_range.size(); ++i) {
470 const Range& range = m_full_module_range[i];
471 if (range.match(expId)) {
472 const Range::field& phi_field = range[m_PHI_INDEX];
473 if (not phi_field.empty()) { return (phi_field.get_maximum()); }
474 }
475 }
476 // Failed to find the max
477 return (-999);
478}
479/*******************************************************************************/
481 ExpandedIdentifier expId;
482 IdContext phi_context(expId, 0, m_PHI_INDEX);
483
484 if (!get_expanded_id(id, expId, &phi_context)) {
485 return stationPhiMax(expId);
486 }
487 // Failed to find the max
488 return (-999);
489}
490/*******************************************************************************/
492 ExpandedIdentifier expId;
493 IdContext context = technology_context();
494 if (!get_expanded_id(id, expId, &context)) {
495 int result = -999;
496 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
497 const Range& range = m_full_channel_range[i];
498 if (range.match(expId)) {
499 const Range::field& multilayer_field = range[m_DETECTORELEMENT_INDEX];
500 if (not multilayer_field.empty()) {
501 int multilayermax = multilayer_field.get_maximum();
502 if (result < multilayermax) result = multilayermax;
503 }
504 }
505 }
506 return (result);
507 }
508 return (-999);
509}
510/*******************************************************************************/
512 int result = -999;
513 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
514 const Range& range = m_full_channel_range[i];
515 if (range.match(expId)) {
516 const Range::field& multilayer_field = range[m_DETECTORELEMENT_INDEX];
517 if (not multilayer_field.empty()) {
518 int multilayermin = multilayer_field.get_minimum();
519 if (-999 == result) {
520 result = multilayermin;
521 } else {
522 if (multilayermin < result) result = multilayermin;
523 }
524 }
525 }
526 }
527 return (result);
528}
529/*******************************************************************************/
531 ExpandedIdentifier expId;
532 IdContext multilayer_context(expId, 0, m_DETECTORELEMENT_INDEX);
533 if (!get_expanded_id(id, expId, &multilayer_context)) {
534 return multilayerMin(expId);
535 }
536 return (999);
537}
538/*******************************************************************************/
540 int result = -999;
541 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
542 const Range& range = m_full_channel_range[i];
543 if (range.match(expId)) {
544 const Range::field& multilayer_field = range[m_DETECTORELEMENT_INDEX];
545 if (not multilayer_field.empty()) {
546 int multilayermax = multilayer_field.get_maximum();
547 if (result < multilayermax) result = multilayermax;
548 }
549 }
550 }
551 return (result);
552}
553/*******************************************************************************/
555 ExpandedIdentifier expId;
556 IdContext multilayer_context(expId, 0, m_DETECTORELEMENT_INDEX);
557 if (!get_expanded_id(id, expId, &multilayer_context)) {
558 return multilayerMax(expId);
559 }
560 return (-999);
561}
562/*******************************************************************************/
564 int result = -999;
565 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
566 const Range& range = m_full_channel_range[i];
567 if (range.match(expId)) {
568 const Range::field& gasgap_field = range[m_GASGAP_INDEX];
569 if (not gasgap_field.empty()) {
570 int gasgapmin = gasgap_field.get_minimum();
571 if (-999 == result) {
572 result = gasgapmin;
573 } else {
574 if (gasgapmin < result) result = gasgapmin;
575 }
576 }
577 }
578 }
579 return (result);
580}
581/*******************************************************************************/
582int MmIdHelper::gasGapMin(const Identifier& id) const {
583 ExpandedIdentifier expId;
584 IdContext gasgap_context(expId, 0, m_GASGAP_INDEX);
585 if (!get_expanded_id(id, expId, &gasgap_context)) {
586 return gasGapMin(expId);
587 }
588 return (999);
589}
590/*******************************************************************************/
592 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
593 const Range& range = m_full_channel_range[i];
594 if (range.match(expId)) {
595 const Range::field& gasgap_field = range[m_GASGAP_INDEX];
596 if (not gasgap_field.empty()) { return (gasgap_field.get_maximum()); }
597 }
598 }
599 // Failed to find the max
600 return (-999);
601}
602/*******************************************************************************/
603int MmIdHelper::gasGapMax(const Identifier& id) const {
604 ExpandedIdentifier expId;
605 IdContext gasgap_context(expId, 0, m_GASGAP_INDEX);
606 if (!get_expanded_id(id, expId, &gasgap_context)) {
607 return gasGapMax(expId);
608 }
609 // Failed to find the max
610 return (-999);
611}
612/*******************************************************************************/
614 int result = -999;
615 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
616 const Range& range = m_full_channel_range[i];
617 if (range.match(expId)) {
618 const Range::field& channel_field = range[m_CHANNEL_INDEX];
619 if (not channel_field.empty()) {
620 int channelmin = channel_field.get_minimum();
621 if (-999 == result) {
622 result = channelmin;
623 } else {
624 if (channelmin < result) result = channelmin;
625 }
626 }
627 }
628 }
629 return (result);
630}
631/*******************************************************************************/
632int MmIdHelper::channelMin(const Identifier& id) const {
633 ExpandedIdentifier expId;
635 if (!get_expanded_id(id, expId, &channel_context)) {
636 return channelMin(expId);
637 }
638 return (999);
639}
640/*******************************************************************************/
642 int result = -999;
643 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
644 const Range& range = m_full_channel_range[i];
645 if (range.match(expId)) {
646 const Range::field& channel_field = range[m_CHANNEL_INDEX];
647 if (not channel_field.empty()) {
648 int channelmax = channel_field.get_maximum();
649 if (result < channelmax) result = channelmax;
650 }
651 }
652 }
653 return (result);
654}
655/*******************************************************************************/
656int MmIdHelper::channelMax(const Identifier& id) const {
657 ExpandedIdentifier expId;
659 if (!get_expanded_id(id, expId, &channel_context)) {
660 return channelMax(expId);
661 }
662 return (-999);
663}
664/*******************************************************************************/
665// validation of levels
666bool MmIdHelper::valid(const Identifier& id) const {
667 return validChannel(id,
668 stationName(id), stationEta(id), stationPhi(id),
669 multilayer(id), gasGap(id), channel(id));
670} // end MmIdHelper::valid
671/*******************************************************************************/
672bool MmIdHelper::isStNameInTech(const std::string& stationName) const { return stationName[0] == 'M'; }
674 ExpandedIdentifier expId;
675 IdContext context(expId, 0, m_PHI_INDEX);
676 if (get_expanded_id(id, expId, &context)) {
677 return false;
678 }
679 return validElement (expId, stationName(id), stationEta(id), stationPhi(id));
680} // end MmIdHelper::validElement
681/*******************************************************************************/
682// Private validation of levels
685 ATH_MSG_DEBUG("Invalid stationName=" << stationNameString(stationName));
686 return false;
687 }
688 if (stationEta < stationEtaMin(expId) || stationEta > stationEtaMax(expId)) {
689 ATH_MSG_DEBUG("Invalid stationEta=" << stationEta << " for stationName=" << stationNameString(stationName)
690 << " stationIndex=" << stationName << " stationEtaMin=" << stationEtaMin(expId)
691 << " stationEtaMax=" << stationEtaMax(expId));
692 return false;
693 }
694 if (stationPhi < stationPhiMin(expId) || stationPhi > stationPhiMax(expId)) {
695 ATH_MSG_DEBUG("Invalid stationPhi=" << stationPhi << " for stationName=" << stationNameString(stationName)
696 << " stationIndex=" << stationName << " stationPhiMin=" << stationPhiMin(expId)
697 << " stationPhiMax=" << stationPhiMax(expId));
698 return false;
699 }
700 return true;
701} // end MmIdHelper::validElement
702/*******************************************************************************/
703// Check values down to readout channel level
705 int channel) const {
706 ExpandedIdentifier expId;
707 IdContext context(expId, 0, m_CHANNEL_INDEX);
708 if (get_expanded_id(id, expId, &context)) {
709 return false;
710 }
711
712 if (!validElement(expId, stationName, stationEta, stationPhi)) return false;
713
714 if ((multilayer < multilayerMin(expId)) || (multilayer > multilayerMax(expId))) {
715 ATH_MSG_DEBUG("Invalid multilayer=" << multilayer << " multilayerMin=" << multilayerMin(expId)
716 << " multilayerMax=" << multilayerMax(expId));
717 return false;
718 }
719
720 if (gasGap < gasGapMin(expId) || gasGap > gasGapMax(expId)) {
721 ATH_MSG_DEBUG("Invalid gasGap=" << gasGap << " gasGapMin=" << gasGapMin(expId) << " gasGapMax=" << gasGapMax(expId));
722 return false;
723 }
724 if (channel < channelMin(expId) || channel > channelMax(expId)) {
725 ATH_MSG_DEBUG("Invalid channel=" << channel << " channelMin=" << channelMin(expId) << " channelMax=" << channelMax(expId));
726 return false;
727 }
728 return true;
729} // end MmIdHelper::validChannel
730 /*******************************************************************************/
731 // Construct ID from components
732
734 // pack fields independently
735 Identifier result((Identifier::value_type)0);
741 return result;
742}
744 try {
746 ExpandedIdentifier expId;
747 IdContext context(expId, 0, m_PHI_INDEX);
748 if (get_expanded_id(result, expId, &context)) {
749 isValid = false;
750 }
751 else {
753 }
754 return result;
755 } catch (const std::out_of_range&) { isValid = false; }
756 return Identifier{0};
757}
758
759/*******************************************************************************/
760Identifier MmIdHelper::elementID(const std::string& stationNameStr, int stationEta, int stationPhi) const {
761 return elementID(stationNameIndex(stationNameStr), stationEta, stationPhi);
762}
763Identifier MmIdHelper::elementID(const std::string& stationNameStr, int stationEta, int stationPhi, bool& isValid) const {
764 return elementID(stationNameIndex(stationNameStr), stationEta, stationPhi, isValid);
765}
766
767/*******************************************************************************/
768Identifier MmIdHelper::elementID(const Identifier& id) const { return parentID(id); }
769/*******************************************************************************/
771 // pack fields independently
772 Identifier result((Identifier::value_type)0);
779 m_gap_impl.pack(gasGap, result);
781 return result;
782}
784 bool& isValid) const {
785 try{
788 return result;
789 } catch (const std::out_of_range&) { isValid = false; }
790 return Identifier{0};
791}
792/*******************************************************************************/
793Identifier MmIdHelper::channelID(const std::string& stationNameStr, int stationEta, int stationPhi, int multilayer, int gasGap, int channel,
794 bool& isValid) const {
796}
797Identifier MmIdHelper::channelID(const std::string& stationNameStr, int stationEta, int stationPhi, int multilayer, int gasGap,
798 int channel) const {
800}
801
802/*******************************************************************************/
811 try {
814 return result;
815 } catch (const std::out_of_range&) { isValid = false; }
816 return Identifier{0};
817}
818/*******************************************************************************/
819// get parent id from strip or gang identifier
821 assert(is_mm(id));
822 Identifier result(id);
823 m_mplet_impl.reset(result);
824 m_gap_impl.reset(result);
825 m_cha_impl.reset(result);
826 return result;
827}
828/*******************************************************************************/
829// Access to components of the ID
830int MmIdHelper::multilayer(const Identifier& id) const { return m_mplet_impl.unpack(id); }
831/*******************************************************************************/
832int MmIdHelper::gasGap(const Identifier& id) const { return m_gap_impl.unpack(id); }
833/*******************************************************************************/
834int MmIdHelper::channel(const Identifier& id) const { return m_cha_impl.unpack(id); }
835/*******************************************************************************/
836// Access to min and max of level ranges
838/*******************************************************************************/
840/*******************************************************************************/
842/*******************************************************************************/
844/*******************************************************************************/
846/*******************************************************************************/
848/*******************************************************************************/
850/*******************************************************************************/
851bool MmIdHelper::isStereo(const Identifier& id) const {
852 bool isStereo = false;
853 int ml = multilayer(id);
854 int gg = gasGap(id);
855 if ((ml == 1 && gg > 2) || (ml == 2 && gg < 3)) isStereo = true;
856 return isStereo;
857}
858/*******************************************************************************/
859bool MmIdHelper::measuresPhi(const Identifier& /*id*/) const { return false; }
860/*******************************************************************************/
862/*******************************************************************************/
864/*******************************************************************************/
866/*******************************************************************************/
869 int mmField = technologyIndex("MM");
870 if (m_dict) { mmField = mm_field_value(); }
871 return mmField;
872}
873/*******************************************************************************/
874bool MmIdHelper::LargeSector(int stationName) const { return ('L' == stationNameString(stationName)[2]); }
875/*******************************************************************************/
876bool MmIdHelper::SmallSector(int stationName) const { return ('S' == stationNameString(stationName)[2]); }
877/*******************************************************************************/
878// Nektar: Modified for MicroMegas, but is almost certainly wrong
879int MmIdHelper::sectorType(const std::string& stationName, int stationEta) {
880 if ('L' == stationName[2]) {
881 return (abs(stationEta) + 1);
882 } else if ('S' == stationName[2]) {
883 return (abs(stationEta) + 12);
884 }
885 assert(0);
886 return -1;
887}
888/*******************************************************************************/
890 std::string name = stationNameString(stationName);
891 return sectorType(name, stationEta);
892}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
bool isValid(const T &p)
Av: we implement here an ATLAS-sepcific convention: all particles which are 99xxxxx are fine.
Definition AtlasPID.h:878
int mm_field_value() const
int muon_field_value() const
virtual int initialize_from_dictionary(const IdDictMgr &dict_mgr) override
Initialization from the identifier dictionary.
bool reinitialize(const IdDictMgr &dict_mgr)
Test whether an idhelper should be reinitialized based on the change of tags.
int register_dict_tag(const IdDictMgr &dict_mgr, const std::string &dict_name)
Register the file and tag names for a particular IdDict dictionary.
std::string show_to_string(Identifier id, const IdContext *context=0, char sep='.') const
or provide the printout in string form
bool is_mm(Identifier id) const
void add(element_type value)
Append a value into a new field.
This class saves the "context" of an expanded identifier (ExpandedIdentifier) for compact or hash ver...
Definition IdContext.h:26
int get_label_value(const std::string &field, const std::string &label, int &value) const
const std::string & name() const
Dictionary name.
const IdDictRegion & region(size_t index) const
const IdDictDictionary * find_dictionary(const std::string &name) const
Access dictionary by name.
size_t index() const
const IdDictFieldImplementation & implementation(size_t i) const
element_type get_minimum() const
Query the values.
bool empty() const
If true, this field does not have any constraints, and may hold any value representable by element_ty...
element_type get_maximum() const
This is a "hash" representation of an Identifier.
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channel) const
static int gasGapMax()
Identifier elementID(int stationName, int stationEta, int stationPhi) const
static int channelMin()
static int stationEtaMax()
IdDictFieldImplementation m_cha_impl
Definition MmIdHelper.h:205
unsigned int detEleHashIdx(const Identifier &id) const
static int channelMax()
Identifier pcbID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int pcb) const
bool LargeSector(int stationName) const
bool validChannel(const Identifier &id, int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channel) const
unsigned int moduleHashIdx(const Identifier &id) const
Identifier multilayerID(const Identifier &channeldID) const
bool isStereo(const Identifier &id) const
virtual int get_detectorElement_hash(const Identifier &id, IdentifierHash &hash_id) const override
bool valid(const Identifier &id) const
IdDictFieldImplementation m_gap_impl
Definition MmIdHelper.h:204
Identifier febID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int radius) const
static int sectorType(const std::string &stationName, int stationEta)
int channel(const Identifier &id) const override
static int gasGapMin()
int numberOfMultilayers(const Identifier &id) const
static int stationPhiMin()
IdDictFieldImplementation m_mplet_impl
Definition MmIdHelper.h:203
virtual int initialize_from_dictionary(const IdDictMgr &dict_mgr) override
Initialization from the identifier dictionary.
std::array< unsigned int, s_detHashDim > m_detectorElement_hashes
Definition MmIdHelper.h:193
bool isStNameInTech(const std::string &stationName) const override
The valid element checks converted the identifier to a stationName string in order to assess whether ...
void idChannels(const Identifier &id, std::vector< Identifier > &vect) const
virtual int get_module_hash(const Identifier &id, IdentifierHash &hash_id) const override
static int stationEtaMin()
int mmTechnology() const
Utility methods.
int gasGap(const Identifier &id) const override
get the hashes
static int multilayerMin()
std::array< unsigned int, s_modHashDim > m_module_hashes
Definition MmIdHelper.h:192
unsigned int m_stationShift
Minimal station index found.
Definition MmIdHelper.h:198
static int getFirstPcbChnl(int stationEta, int pcb)
static constexpr unsigned int s_etaDim
-2, -1 , 1, 2
Definition MmIdHelper.h:183
static constexpr unsigned int s_phiDim
8 phi station
Definition MmIdHelper.h:185
bool SmallSector(int stationName) const
size_type m_GASGAP_INDEX
Definition MmIdHelper.h:201
static int getFirstRadiusChnl(int stationEta, int pcb)
static int multilayerMax()
static int stationPhiMax()
static constexpr unsigned int s_mlDim
2 multilayer
Definition MmIdHelper.h:187
Identifier parentID(const Identifier &id) const
int init_id_to_hashes()
bool validElement(const Identifier &id) const
int multilayer(const Identifier &id) const
bool measuresPhi(const Identifier &id) const override
A MultiRange combines several Ranges.
Definition MultiRange.h:17
size_type size() const
int stationNameIndex(const std::string &name) const
int stationEta(const Identifier &id) const
IdDictFieldImplementation m_phi_impl
size_t m_GROUP_INDEX
IdDictFieldImplementation m_tec_impl
int get_expanded_id(const Identifier &id, ExpandedIdentifier &exp_id, const IdContext *context) const
Create expanded id from compact id (return == 0 for OK)
const std::string & stationNameString(const Identifier &id) const
size_type m_PHI_INDEX
virtual int get_id(const IdentifierHash &hash_id, Identifier &id, const IdContext *context=0) const override
Create compact id from hash id (return == 0 for OK)
size_type m_CHANNEL_INDEX
int technologyIndex(const std::string &name) const
IdDictFieldImplementation m_sta_impl
MultiRange m_full_module_range
IdDictFieldImplementation m_eta_impl
size_type module_hash_max() const
the maximum hash value
MultiRange m_full_detectorElement_range
size_type m_ETA_INDEX
const IdDictDictionary * m_dict
IdContext technology_context() const
access to IdContext's which define which levels or fields are contained in the Muon id
int stationPhi(const Identifier &id) const
size_type m_DETECTORELEMENT_INDEX
int stationName(const Identifier &id) const
int initLevelsFromDict()
id_vec m_detectorElement_vec
virtual int init_detectorElement_hashes()
size_type detectorElement_hash_max() const
IdDictFieldImplementation m_muon_impl
void resetAndSet(const IdDictFieldImplementation &dict, const int new_val, Identifier &id) const
bool validStation(int stationName, int technology) const
MultiRange m_full_channel_range
IdContext channel_context() const
id for channel
MuonIdHelper(const std::string &logName, const std::string &group)
id_vec m_module_vec
size_type m_TECHNOLOGY_INDEX
A Range describes the possible ranges for the field values of an ExpandedIdentifier.
singleton-like access to IMessageSvc via open function and helper
struct color C
Definition index.py:1