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