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 status = 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 status = 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 } else {
87 m_GROUP_INDEX = mmGroup->region(0).index();
88 }
89
90 const IdDictRegion& region = m_dict->region(m_GROUP_INDEX);
97
98 ATH_MSG_DEBUG(" MicroMegas decode index and bit fields for each level: " << std::endl
99 << " muon " << m_muon_impl.show_to_string() << std::endl
100 << " station " << m_sta_impl.show_to_string() << std::endl
101 << " eta " << m_eta_impl.show_to_string() << std::endl
102 << " phi " << m_phi_impl.show_to_string() << std::endl
103 << " technology " << m_tec_impl.show_to_string() << std::endl
104 << " multilayer " << m_mplet_impl.show_to_string()
105 << std::endl
106 << " gasgap " << m_gap_impl.show_to_string() << std::endl
107 << " channel " << m_cha_impl.show_to_string());
108
109 //
110 // Build multirange for the valid set of identifiers
111 //
112
113 // Find value for the field MuonSpectrometer
114 int muonField = -1;
115 const IdDictDictionary* atlasDict = dict_mgr.find_dictionary("ATLAS");
116 if (atlasDict->get_label_value("subdet", "MuonSpectrometer", muonField)) {
117 ATH_MSG_ERROR("Could not get value for label 'MuonSpectrometer' of field 'subdet' in dictionary " << atlasDict->name());
118 return 1;
119 }
120
121 // Build MultiRange down to "technology" for all (muon) regions
122 ExpandedIdentifier region_id;
123 region_id.add(muonField);
124 Range prefix;
125 MultiRange muon_range = m_dict->build_multirange(region_id, prefix, "technology");
126 if (muon_range.size() > 0) {
127 ATH_MSG_INFO("MultiRange built successfully to Technology: "
128 << "MultiRange size is " << muon_range.size());
129 } else {
130 ATH_MSG_ERROR("Muon MultiRange is empty");
131 }
132
133 // Build MultiRange down to "detector element" for all mdt regions
134 ExpandedIdentifier detectorElement_region;
135 detectorElement_region.add(muonField);
136 Range detectorElement_prefix;
137 MultiRange muon_detectorElement_range = m_dict->build_multirange(detectorElement_region, detectorElement_prefix, "mmMultilayer");
138 if (muon_detectorElement_range.size() > 0) {
139 ATH_MSG_INFO("MultiRange built successfully to detector element: "
140 << "Multilayer MultiRange size is " << muon_detectorElement_range.size());
141 } else {
142 ATH_MSG_ERROR("Muon MicroMegas detector element MultiRange is empty");
143 }
144
145 // Build MultiRange down to "channel" for all MM regions
146 ExpandedIdentifier mm_region;
147 mm_region.add(muonField);
148 Range mm_prefix;
149 MultiRange muon_channel_range = m_dict->build_multirange(mm_region, mm_prefix, "mmChannel");
150 if (muon_channel_range.size() > 0) {
151 ATH_MSG_INFO("MultiRange built successfully to channel: "
152 << "MultiRange size is " << muon_channel_range.size());
153 } else {
154 ATH_MSG_ERROR("Muon MultiRange is empty for channels");
155 }
156
157 // build MicroMegas module ranges
158 // Find the regions that have a "technology field" that matches the MM and save them
159 int mmField = -1;
160 status = m_dict->get_label_value("technology", "MM", mmField);
161
162 for (int i = 0; i < (int)muon_range.size(); ++i) {
163 const Range& range = muon_range[i];
164 if (range.fields() > m_TECHNOLOGY_INDEX) {
165 const Range::field& field = range[m_TECHNOLOGY_INDEX];
166 if (field.match((ExpandedIdentifier::element_type)mmField)) {
167 m_full_module_range.add(range);
168 ATH_MSG_DEBUG("field size is " << (int)range.cardinality() << " field index = " << i);
169 }
170 }
171 }
172
173 for (int j = 0; j < (int)muon_detectorElement_range.size(); ++j) {
174 const Range& range = muon_detectorElement_range[j];
175 if (range.fields() > m_TECHNOLOGY_INDEX) {
176 const Range::field& field = range[m_TECHNOLOGY_INDEX];
177 if (field.match((ExpandedIdentifier::element_type)mmField)) {
179 ATH_MSG_DEBUG("detector element field size is " << (int)range.cardinality() << " field index = " << j);
180 }
181 }
182 }
183
184 for (int j = 0; j < (int)muon_channel_range.size(); ++j) {
185 const Range& range = muon_channel_range[j];
186 if (range.fields() > m_TECHNOLOGY_INDEX) {
187 const Range::field& field = range[m_TECHNOLOGY_INDEX];
188 if (field.match((ExpandedIdentifier::element_type)mmField)) {
189 m_full_channel_range.add(range);
190 ATH_MSG_DEBUG("channel field size is " << (int)range.cardinality() << " field index = " << j);
191 }
192 }
193 }
194
195 // test to see that the multi range is not empty
196 if (m_full_module_range.size() == 0) {
197 ATH_MSG_ERROR("MicroMegas MultiRange ID is empty for modules");
198 status = 1;
199 }
200
201 // test to see that the detector element multi range is not empty
202 if (m_full_detectorElement_range.size() == 0) {
203 ATH_MSG_ERROR("MicroMegas MultiRange ID is empty for detector elements");
204 status = 1;
205 }
206
207 // test to see that the multi range is not empty
208 if (m_full_channel_range.size() == 0) {
209 ATH_MSG_ERROR("MicroMegas MultiRange ID is empty for channels");
210 status = 1;
211 }
212
213 // Setup the hash tables for MicroMegas
214 ATH_MSG_INFO("Initializing MicroMegas hash indices ... ");
215 status = init_hashes();
216 status = init_detectorElement_hashes(); // same as module hash
217 status = init_id_to_hashes();
218
219 // Setup hash tables for finding neighbors
220 ATH_MSG_INFO("Initializing MicroMegas hash indices for finding neighbors ... ");
221 status = init_neighbors();
222
223 m_init = true;
224 return (status);
225} // end MmIdHelper::initialize_from_dictionary
226/*******************************************************************************/
227
228inline unsigned int MmIdHelper::moduleHashIdx(const Identifier& id) const{
231 constexpr unsigned int C = s_phiDim;
232 constexpr unsigned int BxC = C*s_etaDim;
233 const int stEta = stationEta(id);
234 return (stationName(id) - m_stationShift)*BxC + (stEta + s_etaDim/2 - (stEta>0))*C + (stationPhi(id) -1);
235}
236inline unsigned int MmIdHelper::detEleHashIdx(const Identifier& id) const{
237 return moduleHashIdx(id) *s_mlDim + (multilayer(id) -1);
238}
239
241 for (const Identifier& id : m_module_vec) m_stationShift = std::min(m_stationShift, 1u* stationName(id));
242 unsigned int hash_max = module_hash_max();
243 for (unsigned int i = 0; i < hash_max; ++i) {
244 const Identifier& id = m_module_vec[i];
245 const unsigned idx = moduleHashIdx(id);
246 if (idx >= m_module_hashes.size() || m_module_hashes[idx] < hash_max){
247 ATH_MSG_FATAL("Failed to assign module hash to "<<show_to_string(id));
248 return 1;
249 }
250 m_module_hashes[idx] = i;
251 }
252
253 hash_max = detectorElement_hash_max();
254 for (unsigned int i = 0; i < hash_max; ++i) {
255 const Identifier& id = m_detectorElement_vec[i];
256 const unsigned idx = detEleHashIdx(id);
257 if (idx >= m_detectorElement_hashes.size() || m_detectorElement_hashes[idx] < hash_max){
258 ATH_MSG_FATAL("Failed to assign detector hash to "<<show_to_string(id));
259 return 1;
260 }
262 }
263 return 0;
264} // end MmIdHelper::init_id_to_hashes()
265/*******************************************************************************/
267 const unsigned int idx = moduleHashIdx(id);
268 if (idx >= m_module_hashes.size()) return 1;
269 hash_id = m_module_hashes[idx];
270 return 0;
271} // end MmIdHelper::get_module_hash
272/*******************************************************************************/
274 const unsigned int idx = detEleHashIdx(id);
275 if (idx >= m_detectorElement_hashes.size()) return 1;
276 hash_id = m_detectorElement_hashes[idx];
277 return 0;
278 // return get_module_hash(id, hash_id);
279}
280/*******************************************************************************/
282 assert(is_mm(channelID));
284 // m_mplet_impl.reset(result);
285 m_gap_impl.reset(result);
286 m_cha_impl.reset(result);
287 return result;
288}
289/*******************************************************************************/
291 Identifier result(moduleID);
293 return result;
294}
296 try {
297 const Identifier result = multilayerID(moduleID, multilayer);
299 return result;
300 } catch (const std::out_of_range&) { isValid = false; }
301 return Identifier{0};
302}
303/*******************************************************************************/
305 int pcbNb = std::abs(stationEta)==1 ? pcb : pcb-5;
306 return (pcbNb-1)*1024+1;
307}
309 int chnl = getFirstPcbChnl(stationEta, pcb);
311}
313 int chnl = getFirstPcbChnl(stationEta, pcb);
315}
316Identifier MmIdHelper::pcbID(const std::string& stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int pcb) const {
317 int chnl = getFirstPcbChnl(stationEta, pcb);
319}
320Identifier MmIdHelper::pcbID(const std::string& stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int pcb, bool& isValid) const {
321 int chnl = getFirstPcbChnl(stationEta, pcb);
323}
324Identifier MmIdHelper::pcbID(const Identifier& channelId, int pcb) const {
325 int chnl = getFirstPcbChnl(stationEta(channelId), pcb);
326 return channelID(channelId, multilayer(channelId), gasGap(channelId), chnl);
327}
328Identifier MmIdHelper::pcbID(const Identifier& channelId, int pcb, bool& isValid) const {
329 int chnl = getFirstPcbChnl(stationEta(channelId), pcb);
330 return channelID(channelId, multilayer(channelId), gasGap(channelId), chnl, isValid);
331}
332Identifier MmIdHelper::pcbID(const Identifier& channelId) const {
333 int chnl = channel(channelId);
334 // PCB counts from 1-8. PCBs 1-5 are in abs(stationEta)==1 and PCBs 6-8 in abs(stationEta)==2
335 // each PCB consists of 1024 readout strips (strip number in athena is counting from 1 therefore chnl -1)
336 int pcb = (chnl-1)/1024+1 + (std::abs(stationEta(channelId))==2 ? 5:0); // int division should round downwards
337 return pcbID(channelId, pcb);
338}
339/*******************************************************************************/
341 int radiusNb = std::abs(stationEta)==1 ? radius : radius-10;
342 return radiusNb*512+1;
343}
345 int chnl = getFirstRadiusChnl(stationEta, radius);
347}
348Identifier MmIdHelper::febID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int radius, bool& isValid) const {
349 int chnl = getFirstRadiusChnl(stationEta, radius);
351}
352Identifier MmIdHelper::febID(const std::string& stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int radius) const {
353 int chnl = getFirstRadiusChnl(stationEta, radius);
355}
356Identifier MmIdHelper::febID(const std::string& stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int radius, bool& isValid) const {
357 int chnl = getFirstRadiusChnl(stationEta, radius);
359}
360Identifier MmIdHelper::febID(const Identifier& channelId, int radius) const {
361 int chnl = getFirstRadiusChnl(stationEta(channelId), radius);
362 return channelID(channelId, multilayer(channelId), gasGap(channelId), chnl);
363}
364Identifier MmIdHelper::febID(const Identifier& channelId, int radius, bool& isValid) const {
365 int chnl = getFirstRadiusChnl(stationEta(channelId), radius);
366 return channelID(channelId, multilayer(channelId), gasGap(channelId), chnl, isValid);
367}
368Identifier MmIdHelper::febID(const Identifier& channelId) const {
369 int chnl = channel(channelId);
370 // radius counts from 0-15. Radii 0-9 are in abs(stationEta)==1 and radii 10-15 in abs(stationEta)==2
371 // each radius consists of 512 readout strips (strip number in athena is counting from 1 therefore chnl -1)
372 int radius = (chnl-1)/512 + (std::abs(stationEta(channelId))==2 ? 10:0); // int division should round downwards
373 return febID(channelId, radius);
374}
375/*******************************************************************************/
376void MmIdHelper::idChannels(const Identifier& id, std::vector<Identifier>& vect) const {
377 vect.clear();
378 Identifier parent = parentID(id);
379 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
380 const Range& range = m_full_channel_range[i];
381 ConstRangeIterator rit(range);
382 for (const auto & expId : rit) {
383 Identifier child;
384 get_id(expId, child);
385 if (parentID(child) == parent) vect.push_back(child);
386 }
387 }
388}
389/*******************************************************************************/
391 int result = -999;
392 for (unsigned int i = 0; i < m_full_module_range.size(); ++i) {
393 const Range& range = m_full_module_range[i];
394 if (range.match(expId)) {
395 const Range::field& eta_field = range[m_ETA_INDEX];
396 if (not eta_field.empty()) {
397 int etamin = eta_field.get_minimum();
398 if (-999 == result) {
399 result = etamin;
400 } else {
401 if (etamin < result) result = etamin;
402 }
403 }
404 }
405 }
406 return (result);
407} // end MmIdHelper::stationEtaMin
408/*******************************************************************************/
410 ExpandedIdentifier expId;
411 IdContext eta_context(expId, 0, m_ETA_INDEX);
412 if (!get_expanded_id(id, expId, &eta_context)) {
413 return stationEtaMin(expId);
414 }
415 return (999); // default
416} // end MmIdHelper::stationEtaMin
417/*******************************************************************************/
419 int result = -999;
420 for (unsigned int i = 0; i < m_full_module_range.size(); ++i) {
421 const Range& range = m_full_module_range[i];
422 if (range.match(expId)) {
423 const Range::field& eta_field = range[m_ETA_INDEX];
424 if (not eta_field.empty()) {
425 int etamax = eta_field.get_maximum();
426 if (result < etamax) result = etamax;
427 }
428 }
429 }
430 return (result);
431} // end MmIdHelper::stationEtaMax
432/*******************************************************************************/
434 ExpandedIdentifier expId;
435 IdContext eta_context(expId, 0, m_ETA_INDEX);
436 if (!get_expanded_id(id, expId, &eta_context)) {
437 return stationEtaMax(expId);
438 }
439 return (-999);
440} // end MmIdHelper::stationEtaMax
441/*******************************************************************************/
443 for (unsigned int i = 0; i < m_full_module_range.size(); ++i) {
444 const Range& range = m_full_module_range[i];
445 if (range.match(expId)) {
446 const Range::field& phi_field = range[m_PHI_INDEX];
447 if (not phi_field.empty()) { return (phi_field.get_minimum()); }
448 }
449 }
450 // Failed to find the min
451 return (999);
452}
453/*******************************************************************************/
455 ExpandedIdentifier expId;
456 IdContext phi_context(expId, 0, m_PHI_INDEX);
457
458 if (!get_expanded_id(id, expId, &phi_context)) {
459 return stationPhiMin(expId);
460 }
461 // Failed to find the min
462 return (999);
463}
464/*******************************************************************************/
466 for (unsigned int i = 0; i < m_full_module_range.size(); ++i) {
467 const Range& range = m_full_module_range[i];
468 if (range.match(expId)) {
469 const Range::field& phi_field = range[m_PHI_INDEX];
470 if (not phi_field.empty()) { return (phi_field.get_maximum()); }
471 }
472 }
473 // Failed to find the max
474 return (-999);
475}
476/*******************************************************************************/
478 ExpandedIdentifier expId;
479 IdContext phi_context(expId, 0, m_PHI_INDEX);
480
481 if (!get_expanded_id(id, expId, &phi_context)) {
482 return stationPhiMax(expId);
483 }
484 // Failed to find the max
485 return (-999);
486}
487/*******************************************************************************/
489 ExpandedIdentifier expId;
490 IdContext context = technology_context();
491 if (!get_expanded_id(id, expId, &context)) {
492 int result = -999;
493 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
494 const Range& range = m_full_channel_range[i];
495 if (range.match(expId)) {
496 const Range::field& multilayer_field = range[m_DETECTORELEMENT_INDEX];
497 if (not multilayer_field.empty()) {
498 int multilayermax = multilayer_field.get_maximum();
499 if (result < multilayermax) result = multilayermax;
500 }
501 }
502 }
503 return (result);
504 }
505 return (-999);
506}
507/*******************************************************************************/
509 int result = -999;
510 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
511 const Range& range = m_full_channel_range[i];
512 if (range.match(expId)) {
513 const Range::field& multilayer_field = range[m_DETECTORELEMENT_INDEX];
514 if (not multilayer_field.empty()) {
515 int multilayermin = multilayer_field.get_minimum();
516 if (-999 == result) {
517 result = multilayermin;
518 } else {
519 if (multilayermin < result) result = multilayermin;
520 }
521 }
522 }
523 }
524 return (result);
525}
526/*******************************************************************************/
528 ExpandedIdentifier expId;
529 IdContext multilayer_context(expId, 0, m_DETECTORELEMENT_INDEX);
530 if (!get_expanded_id(id, expId, &multilayer_context)) {
531 return multilayerMin(expId);
532 }
533 return (999);
534}
535/*******************************************************************************/
537 int result = -999;
538 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
539 const Range& range = m_full_channel_range[i];
540 if (range.match(expId)) {
541 const Range::field& multilayer_field = range[m_DETECTORELEMENT_INDEX];
542 if (not multilayer_field.empty()) {
543 int multilayermax = multilayer_field.get_maximum();
544 if (result < multilayermax) result = multilayermax;
545 }
546 }
547 }
548 return (result);
549}
550/*******************************************************************************/
552 ExpandedIdentifier expId;
553 IdContext multilayer_context(expId, 0, m_DETECTORELEMENT_INDEX);
554 if (!get_expanded_id(id, expId, &multilayer_context)) {
555 return multilayerMax(expId);
556 }
557 return (-999);
558}
559/*******************************************************************************/
561 int result = -999;
562 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
563 const Range& range = m_full_channel_range[i];
564 if (range.match(expId)) {
565 const Range::field& gasgap_field = range[m_GASGAP_INDEX];
566 if (not gasgap_field.empty()) {
567 int gasgapmin = gasgap_field.get_minimum();
568 if (-999 == result) {
569 result = gasgapmin;
570 } else {
571 if (gasgapmin < result) result = gasgapmin;
572 }
573 }
574 }
575 }
576 return (result);
577}
578/*******************************************************************************/
579int MmIdHelper::gasGapMin(const Identifier& id) const {
580 ExpandedIdentifier expId;
581 IdContext gasgap_context(expId, 0, m_GASGAP_INDEX);
582 if (!get_expanded_id(id, expId, &gasgap_context)) {
583 return gasGapMin(expId);
584 }
585 return (999);
586}
587/*******************************************************************************/
589 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
590 const Range& range = m_full_channel_range[i];
591 if (range.match(expId)) {
592 const Range::field& gasgap_field = range[m_GASGAP_INDEX];
593 if (not gasgap_field.empty()) { return (gasgap_field.get_maximum()); }
594 }
595 }
596 // Failed to find the max
597 return (-999);
598}
599/*******************************************************************************/
600int MmIdHelper::gasGapMax(const Identifier& id) const {
601 ExpandedIdentifier expId;
602 IdContext gasgap_context(expId, 0, m_GASGAP_INDEX);
603 if (!get_expanded_id(id, expId, &gasgap_context)) {
604 return gasGapMax(expId);
605 }
606 // Failed to find the max
607 return (-999);
608}
609/*******************************************************************************/
611 int result = -999;
612 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
613 const Range& range = m_full_channel_range[i];
614 if (range.match(expId)) {
615 const Range::field& channel_field = range[m_CHANNEL_INDEX];
616 if (not channel_field.empty()) {
617 int channelmin = channel_field.get_minimum();
618 if (-999 == result) {
619 result = channelmin;
620 } else {
621 if (channelmin < result) result = channelmin;
622 }
623 }
624 }
625 }
626 return (result);
627}
628/*******************************************************************************/
629int MmIdHelper::channelMin(const Identifier& id) const {
630 ExpandedIdentifier expId;
632 if (!get_expanded_id(id, expId, &channel_context)) {
633 return channelMin(expId);
634 }
635 return (999);
636}
637/*******************************************************************************/
639 int result = -999;
640 for (unsigned int i = 0; i < m_full_channel_range.size(); ++i) {
641 const Range& range = m_full_channel_range[i];
642 if (range.match(expId)) {
643 const Range::field& channel_field = range[m_CHANNEL_INDEX];
644 if (not channel_field.empty()) {
645 int channelmax = channel_field.get_maximum();
646 if (result < channelmax) result = channelmax;
647 }
648 }
649 }
650 return (result);
651}
652/*******************************************************************************/
653int MmIdHelper::channelMax(const Identifier& id) const {
654 ExpandedIdentifier expId;
656 if (!get_expanded_id(id, expId, &channel_context)) {
657 return channelMax(expId);
658 }
659 return (-999);
660}
661/*******************************************************************************/
662// validation of levels
663bool MmIdHelper::valid(const Identifier& id) const {
664 return validChannel(id,
665 stationName(id), stationEta(id), stationPhi(id),
666 multilayer(id), gasGap(id), channel(id));
667} // end MmIdHelper::valid
668/*******************************************************************************/
669bool MmIdHelper::isStNameInTech(const std::string& stationName) const { return stationName[0] == 'M'; }
671 ExpandedIdentifier expId;
672 IdContext context(expId, 0, m_PHI_INDEX);
673 if (get_expanded_id(id, expId, &context)) {
674 return false;
675 }
676 return validElement (expId, stationName(id), stationEta(id), stationPhi(id));
677} // end MmIdHelper::validElement
678/*******************************************************************************/
679// Private validation of levels
682 ATH_MSG_DEBUG("Invalid stationName=" << stationNameString(stationName));
683 return false;
684 }
685 if (stationEta < stationEtaMin(expId) || stationEta > stationEtaMax(expId)) {
686 ATH_MSG_DEBUG("Invalid stationEta=" << stationEta << " for stationName=" << stationNameString(stationName)
687 << " stationIndex=" << stationName << " stationEtaMin=" << stationEtaMin(expId)
688 << " stationEtaMax=" << stationEtaMax(expId));
689 return false;
690 }
691 if (stationPhi < stationPhiMin(expId) || stationPhi > stationPhiMax(expId)) {
692 ATH_MSG_DEBUG("Invalid stationPhi=" << stationPhi << " for stationName=" << stationNameString(stationName)
693 << " stationIndex=" << stationName << " stationPhiMin=" << stationPhiMin(expId)
694 << " stationPhiMax=" << stationPhiMax(expId));
695 return false;
696 }
697 return true;
698} // end MmIdHelper::validElement
699/*******************************************************************************/
700// Check values down to readout channel level
702 int channel) const {
703 ExpandedIdentifier expId;
704 IdContext context(expId, 0, m_CHANNEL_INDEX);
705 if (get_expanded_id(id, expId, &context)) {
706 return false;
707 }
708
709 if (!validElement(expId, stationName, stationEta, stationPhi)) return false;
710
711 if ((multilayer < multilayerMin(expId)) || (multilayer > multilayerMax(expId))) {
712 ATH_MSG_DEBUG("Invalid multilayer=" << multilayer << " multilayerMin=" << multilayerMin(expId)
713 << " multilayerMax=" << multilayerMax(expId));
714 return false;
715 }
716
717 if (gasGap < gasGapMin(expId) || gasGap > gasGapMax(expId)) {
718 ATH_MSG_DEBUG("Invalid gasGap=" << gasGap << " gasGapMin=" << gasGapMin(expId) << " gasGapMax=" << gasGapMax(expId));
719 return false;
720 }
721 if (channel < channelMin(expId) || channel > channelMax(expId)) {
722 ATH_MSG_DEBUG("Invalid channel=" << channel << " channelMin=" << channelMin(expId) << " channelMax=" << channelMax(expId));
723 return false;
724 }
725 return true;
726} // end MmIdHelper::validChannel
727 /*******************************************************************************/
728 // Construct ID from components
729
731 // pack fields independently
732 Identifier result((Identifier::value_type)0);
738 return result;
739}
741 try {
743 ExpandedIdentifier expId;
744 IdContext context(expId, 0, m_PHI_INDEX);
745 if (get_expanded_id(result, expId, &context)) {
746 isValid = false;
747 }
748 else {
750 }
751 return result;
752 } catch (const std::out_of_range&) { isValid = false; }
753 return Identifier{0};
754}
755
756/*******************************************************************************/
757Identifier MmIdHelper::elementID(const std::string& stationNameStr, int stationEta, int stationPhi) const {
758 return elementID(stationNameIndex(stationNameStr), stationEta, stationPhi);
759}
760Identifier MmIdHelper::elementID(const std::string& stationNameStr, int stationEta, int stationPhi, bool& isValid) const {
761 return elementID(stationNameIndex(stationNameStr), stationEta, stationPhi, isValid);
762}
763
764/*******************************************************************************/
765Identifier MmIdHelper::elementID(const Identifier& id) const { return parentID(id); }
766/*******************************************************************************/
768 // pack fields independently
769 Identifier result((Identifier::value_type)0);
776 m_gap_impl.pack(gasGap, result);
778 return result;
779}
781 bool& isValid) const {
782 try{
785 return result;
786 } catch (const std::out_of_range&) { isValid = false; }
787 return Identifier{0};
788}
789/*******************************************************************************/
790Identifier MmIdHelper::channelID(const std::string& stationNameStr, int stationEta, int stationPhi, int multilayer, int gasGap, int channel,
791 bool& isValid) const {
793}
794Identifier MmIdHelper::channelID(const std::string& stationNameStr, int stationEta, int stationPhi, int multilayer, int gasGap,
795 int channel) const {
797}
798
799/*******************************************************************************/
808 try {
811 return result;
812 } catch (const std::out_of_range&) { isValid = false; }
813 return Identifier{0};
814}
815/*******************************************************************************/
816// get parent id from strip or gang identifier
818 assert(is_mm(id));
819 Identifier result(id);
820 m_mplet_impl.reset(result);
821 m_gap_impl.reset(result);
822 m_cha_impl.reset(result);
823 return result;
824}
825/*******************************************************************************/
826// Access to components of the ID
827int MmIdHelper::multilayer(const Identifier& id) const { return m_mplet_impl.unpack(id); }
828/*******************************************************************************/
829int MmIdHelper::gasGap(const Identifier& id) const { return m_gap_impl.unpack(id); }
830/*******************************************************************************/
831int MmIdHelper::channel(const Identifier& id) const { return m_cha_impl.unpack(id); }
832/*******************************************************************************/
833// Access to min and max of level ranges
835/*******************************************************************************/
837/*******************************************************************************/
839/*******************************************************************************/
841/*******************************************************************************/
843/*******************************************************************************/
845/*******************************************************************************/
847/*******************************************************************************/
848bool MmIdHelper::isStereo(const Identifier& id) const {
849 bool isStereo = false;
850 int ml = multilayer(id);
851 int gg = gasGap(id);
852 if ((ml == 1 && gg > 2) || (ml == 2 && gg < 3)) isStereo = true;
853 return isStereo;
854}
855/*******************************************************************************/
856bool MmIdHelper::measuresPhi(const Identifier& /*id*/) const { return false; }
857/*******************************************************************************/
859/*******************************************************************************/
861/*******************************************************************************/
863/*******************************************************************************/
866 int mmField = technologyIndex("MM");
867 if (m_dict) { mmField = mm_field_value(); }
868 return mmField;
869}
870/*******************************************************************************/
871bool MmIdHelper::LargeSector(int stationName) const { return ('L' == stationNameString(stationName)[2]); }
872/*******************************************************************************/
873bool MmIdHelper::SmallSector(int stationName) const { return ('S' == stationNameString(stationName)[2]); }
874/*******************************************************************************/
875// Nektar: Modified for MicroMegas, but is almost certainly wrong
876int MmIdHelper::sectorType(const std::string& stationName, int stationEta) {
877 if ('L' == stationName[2]) {
878 return (abs(stationEta) + 1);
879 } else if ('S' == stationName[2]) {
880 return (abs(stationEta) + 12);
881 }
882 assert(0);
883 return -1;
884}
885/*******************************************************************************/
887 std::string name = stationNameString(stationName);
888 return sectorType(name, stationEta);
889}
#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
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)
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
bool is_mm(const Identifier &id) const
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
const std::string & stationNameString(const int &index) const
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