9#include "GaudiKernel/ISvcLocator.h"
13#include "Identifier/Identifier.h"
15#include "GeoModelKernel/throwExcept.h"
22static const std::set<uint8_t> special_cards{50, 60, 61, 71};
30 ISvcLocator* svcLocator = Gaudi::svcLocator();
31 SmartIF<StoreGateSvc> detStore{svcLocator->service(
"DetectorStore")};
35 StatusCode sc = detStore->retrieve(
m_mdtIdHelper,
"MDTIDHELPER");
36 if (sc != StatusCode::SUCCESS) {
46 bool valid{!check_valid};
48 cabling_data.stationIndex, cabling_data.eta,
49 cabling_data.phi, cabling_data.multilayer,
50 cabling_data.layer, cabling_data.tube, valid)
52 cabling_data.stationIndex, cabling_data.eta,
53 cabling_data.phi, cabling_data.multilayer,
54 cabling_data.layer, cabling_data.tube);
61 cabling_data.stationIndex =
m_mdtIdHelper->stationName(module_id);
65 cabling_data.multilayer =
m_mdtIdHelper->multilayer(module_id);
72 const int sequence, MsgStream& log) {
73 const bool debug = (log.level() <= MSG::VERBOSE);
74 if (special_cards.count(
type)) {
76 log << MSG::VERBOSE <<
"Mezzanine type " <<
type
77 <<
" breaks the legacy database format. No need to add the "
78 "card if it's hardcoded in C++"
83 int nOfLayers{0}, ntubes{0},
number{sequence};
84 std::array<int, 8> newseq{};
91 log << MSG::ERROR <<
"More than 8 tubes in a layer, not possible !"
96 log << MSG::VERBOSE <<
"Adding tube number: " << tube
97 <<
" to the layer " << layer <<
" of mezzanine type " <<
type
101 newseq[ntubes] = tube;
108 if (ntubes != 8 && ntubes != 6) {
109 log << MSG::ERROR <<
"in type " <<
type
110 <<
": number of tubes per mezzanine layer can be only 6 or 8 ! "
111 "what are you doing ???"
115 nOfLayers = 24 / ntubes;
116 if (layer > nOfLayers) {
118 <<
"The maximum number of layers for this mezzanine is: "
119 << nOfLayers <<
" so you can't initialize layer: " << layer
125 log << MSG::VERBOSE <<
"Found " << ntubes <<
" tubes in layer " << layer
127 log << MSG::VERBOSE <<
"This is a " << nOfLayers
128 <<
" layers mezzanine - OK, OK..." <<
endmsg;
132 std::array<uint8_t, 8> newLayer{};
133 for (
int i = 0; i < ntubes; ++i) {
134 newLayer[i] = newseq[ntubes - i - 1];
136 MezzCardList::iterator itr = std::find_if(
141 MezzMapping new_map =
143 ? (**itr).tdcToTubeMap()
148 for (
int i = 0; i < ntubes; ++i) {
150 const int chStart = ntubes * (layer - 1);
151 new_map[chStart + i] = dummy_card.
tubeNumber(layer, newLayer[i]);
153 for (
int lay = 1; lay <= nOfLayers; ++lay) {
154 const int chStart = ntubes * (lay - 1);
155 new_map[chStart + i] = dummy_card.
tubeNumber(lay, newLayer[i]);
162 log << MSG::ERROR <<
"The mezzanine type " <<
type
163 <<
"has been already initialized" <<
endmsg;
166 (*itr) = std::make_unique<MdtMezzanineCard>(new_map, nOfLayers,
type);
168 log << MSG::VERBOSE <<
"Updated mezzanine " << (**itr) <<
endmsg;
171 std::make_unique<MdtMezzanineCard>(new_map, nOfLayers,
type));
173 log << MSG::VERBOSE <<
" Added new mezzanine "
180 MezzCardList::const_iterator it = std::find_if(
182 [&](
const MezzCardPtr& card) { return card->id() == mezzCardId; });
188 bool debug = (log.level() <= MSG::VERBOSE);
190 MezzCardPtr mezzaType = source == DataSource::LegacyCOOL
195 <<
"Mezzanine Type: " <<
static_cast<int>(map_data.
mezzanine_type)
196 <<
" not found in the list !" <<
endmsg;
198 }
else if (source == DataSource::LegacyCOOL && !mezzaType->
checkConsistency(log)){
201 auto newTdc = std::make_unique<MdtTdcMap>(mezzaType, map_data);
203 log << MSG::VERBOSE <<
" Added new readout channel " << map_data<<
endmsg;
206 offModule.
cards.emplace(newTdc.get());
207 if (!offModule.
csm[0]) {
208 offModule.
csm[0] = map_data;
210 log<< MSG::VERBOSE<<
"Assign first CSM "<<map_data<<
endmsg;
217 if (!secondModule.
csm[0]){
218 secondModule.
csm[0] = map_data;
219 }
else if (secondModule.
csm[0] != map_data && !secondModule.
csm[1]) {
220 secondModule.
csm[1] = map_data;
224 }
else if (offModule.
csm[0] != map_data) {
225 if (!offModule.
csm[1]) {
226 offModule.
csm[1] = map_data;
228 log << MSG::VERBOSE <<
" Add second CSM for " << map_data <<
endmsg;
230 }
else if (offModule.
csm[1] != map_data) {
231 log << MSG::ERROR <<
"The mulit layer " << map_data
232 <<
" has already associated the CSMs " << std::endl
233 <<
" *** " << offModule.
csm[0] << std::endl
234 <<
" *** " << offModule.
csm[1] << std::endl
235 <<
", while this one is a third one and not supported"
241 if (attachedTdcs.size() <= map_data.
tdcId)
242 attachedTdcs.resize(map_data.
tdcId + 1);
244 m_tdcs.push_back(std::move(newTdc));
247 log << MSG::VERBOSE <<
"Station already in the map !" <<
endmsg;
253 MsgStream& log)
const {
254 OnlToOffMap::const_iterator module_itr =
m_toOfflineConv.find(cabling_map);
257 <<
"Could not find a cabling module to recieve offline Id for "
264 if (!module_itr->second.zero_module) {
265 log << MSG::WARNING <<
" No tdc with channel zero found for "
266 << module_itr->first <<
endmsg;
269 if (!module_itr->second.zero_module->offlineId(cabling_map, log)) {
270 log << MSG::WARNING <<
"MdtTdMap::getOfflineId() -- Channel: "
271 <<
static_cast<unsigned>(cabling_map.
channelId)
272 <<
" Tdc: " <<
static_cast<unsigned>(cabling_map.
tdcId)
278 const TdcOnlSet& attachedTdcs = module_itr->second.all_modules;
279 if (attachedTdcs.size() <= cabling_map.
tdcId) {
280 log << MSG::WARNING <<
"getOfflineId() -- Tdc: "
281 <<
static_cast<unsigned>(cabling_map.
tdcId)
282 <<
" is not part of " << module_itr->first <<
". Maximally "
283 << attachedTdcs.size() <<
" Tdcs were attached. " <<
endmsg;
288 log << MSG::WARNING <<
"getOfflineId() -- Tdc: "
289 <<
static_cast<unsigned>(cabling_map.
tdcId) <<
" not found in "
293 if (!TdcItr->
offlineId(cabling_map, log)) {
294 log << MSG::WARNING <<
"MdtTdMap::getOfflineId() -- channel: "
295 <<
static_cast<unsigned>(cabling_map.
channelId)
296 <<
" Tdc: " <<
static_cast<unsigned>(cabling_map.
tdcId)
302 if (log.level() <= MSG::VERBOSE) {
304 <<
"Channel: " <<
static_cast<unsigned>(cabling_map.
channelId)
305 <<
" Tdc: " <<
static_cast<unsigned>(cabling_map.
tdcId) <<
" "
308 log << MSG::VERBOSE <<
"Mapped to "
310 <<
" layer: " << cabling_map.
layer <<
" tube: " << cabling_map.
tube
318 MsgStream& log)
const {
319 OffToOnlMap::const_iterator module_itr =
m_toOnlineConv.find(cabling_map);
322 <<
"getOnlineId() --- Could not find a cabling CSM set recieve "
327 const TdcOffSet& attachedTdcs = module_itr->second.cards;
328 TdcOffSet::const_iterator tdc_itr = attachedTdcs.find(cabling_map);
329 if (tdc_itr == attachedTdcs.end()) {
330 log << MSG::WARNING <<
"No matching Tdc channel was found for "
332 }
else if ((*tdc_itr)->onlineId(cabling_map, log))
335 TdcOffSet::const_iterator control_itr =
336 std::find_if(attachedTdcs.begin(), attachedTdcs.end(),
338 return tdc->onlineId(cabling_map, log);
340 if (control_itr == attachedTdcs.end()) {
342 <<
"Second trial to find a valid cabling channel for "
343 << cabling_map <<
" failed as well. " <<
endmsg;
359 bool debug = (log.level() <= MSG::VERBOSE);
363 log << MSG::ERROR <<
"Could not find hashId for station: " << map_data
368 log << MSG::ERROR <<
"Could not find hashId for multi layer: " << map_data <<
endmsg;
372 int rod = map_data.
mrod;
374 uint32_t hardId = (sub << 16) | rod;
376 log << MSG::VERBOSE <<
"Adding the chamber with Id: " << chamberId
377 <<
" and subdetector+rod ID: " << hardId <<
endmsg;
390 const bool robInitialized =
393 if (!robInitialized) {
395 log << MSG::VERBOSE <<
"Adding the ROB " << hardId <<
" to the list"
403 MsgStream& log)
const {
405 OffToOnlMap::const_iterator off_itr =
m_toOnlineConv.find(map_data);
407 log << MSG::ERROR <<
"csmNumOnChamber() -- Nothing is saved under "
411 return (1 * (off_itr->second.csm[0] == map_data)) +
412 (2 * (off_itr->second.csm[1] == map_data));
416 MsgStream& log)
const {
421 <<
"getstationCode() -- Could not find HashId for module: "
434 MsgStream& log)
const {
438 <<
"getMultiLayerCode() -- Could not determine the detector layer "
444 map_data.
phi, ml, 1, 1);
448 m_mdtIdHelper->get_detectorElement_hash(elementId, mdtHashId)) {
450 <<
"getMultiLayerCode() -- Could not find HashId for module: "
460 <<
"getMultiLayerCode() -- Could not find HashId for module: "
468 MsgStream& log)
const {
469 ChamberToROBMap::const_iterator it =
m_chamberToROB.find(stationCode);
473 log << MSG::WARNING <<
"ROB ID " << stationCode <<
" not found !" <<
endmsg;
479 const std::vector<IdentifierHash>& mdtHashVector, MsgStream& log)
const {
480 std::vector<uint32_t> robVector;
481 bool debug = (log.level() <= MSG::VERBOSE);
482 for (
unsigned int i = 0; i < mdtHashVector.size(); ++i) {
483 int robId =
getROBId(mdtHashVector[i], log);
486 <<
"ROB id not found for Hash Id: " << mdtHashVector[i]
489 log << MSG::VERBOSE <<
"Found ROB id " << robId <<
" for hashId "
490 << mdtHashVector[i] <<
endmsg;
492 robVector.push_back(robId);
495 log << MSG::VERBOSE <<
"Size of ROB vector is: " << robVector.size()
502 const uint32_t ROBId, MsgStream& log)
const {
505 return Rob_it->second;
508 log << MSG::WARNING <<
"Rod ID not found !" <<
endmsg;
509 static const std::vector<IdentifierHash> emptyIdHashVec{};
510 return emptyIdHashVec;
514 const std::vector<uint32_t>& ROBId_list, MsgStream& log)
const {
515 std::vector<IdentifierHash> HashVec;
516 for (
unsigned int i = 0; i < ROBId_list.size(); ++i) {
517 ROBToChamberMap::const_iterator Rob_it =
520 log << MSG::WARNING <<
"Rod ID " << ROBId_list[i]
521 <<
" not found, continuing with the rest of the ROBId"
525 HashVec.insert(HashVec.end(), Rob_it->second.begin(),
526 Rob_it->second.end());
537 log << MSG::ERROR <<
"No tdc maps were loaded " <<
endmsg;
541 if (!card->checkConsistency(log))
545 const unsigned int offToOnlChan =
547 [](
unsigned int N,
const auto&
map) {
548 return N + map.second.cards.size();
550 const unsigned int onlToOffChan = std::accumulate(
552 [](
unsigned int N,
const auto&
map) {
553 return N + std::accumulate(map.second.begin(), map.second.end(), 0,
554 [](unsigned int M, const auto& tdc) {
559 if (offToOnlChan != onlToOffChan || onlToOffChan != m_tdcs.size()) {
561 <<
"Offline <-> online conversion channels were lost. Expect "
563 <<
" cabling channels. Counted Offline -> online channels "
564 << offToOnlChan <<
". Conted Online -> offline channels "
565 << onlToOffChan <<
endmsg;
568 for (
auto& toOff : m_toOfflineConv) {
569 MdtTdcModule&
mod = toOff.second;
570 TdcOnlSet::const_iterator itr = std::find_if(
572 return sorter && sorter->tdcZero() == 0;
574 if (itr ==
mod.end()) {
575 log << MSG::ERROR <<
"There is no tdc with channel 0 in "
577 <<
". That is important to decode the station names later"
581 mod.zero_module = (*itr);
584 log << MSG::INFO <<
"MdtCabling successfully loaded. Found in total "
585 << m_tdcs.size() <<
" channels." <<
endmsg;
589 std::unique_ptr<MdtMezzanineCard> card, MsgStream& log) {
590 if (!card->checkConsistency(log))
592 MezzCardList::const_iterator itr =
595 return existing->id() == card->id();
598 log << MSG::ERROR <<
"Mezzanine card " << std::endl
599 << (*card) <<
" has already been added " << std::endl
600 << (**itr) << std::endl
601 <<
" please check. " <<
endmsg;
608 MsgStream&
msg)
const {
612 const int mezzType = cabling.mezzanine_type;
613 const int chanZero = cabling.channelId;
614 const int layerZero = cabling.layer;
615 const int tubeZero = cabling.tube;
618 const bool debug =
msg.level() <= MSG::VERBOSE;
620 if (special_cards.count(mezzType)) {
624 <<
"legacyHedgehogCard() -- Special layout given " << mezzType
626 for (
size_t chan = 0; chan < chMap.size(); ++chan) {
627 uint8_t tube_chan = ((chan - chan % 4) / 4);
630 if (mezzType == 71) {
631 tube_chan = 5 - tube_chan;
633 int layer{0}, tube{0};
652 if (mezzType == 50 || mezzType == 60 || mezzType == 61) {
654 if (layerZero == 1) {
655 layer = chan % 4 + 1;
659 layer = 4 - chan % 4;
661 if ((tubeZero - 1) % 6 == 0) {
662 tube = tubeZero + tube_chan;
664 tube = tubeZero - tube_chan;
674 else if (mezzType == 71) {
676 layer += 2 * (layer > 1 ? -1 : +1) + 1;
677 tube = tubeZero - tube_chan;
679 cabling.tube = std::min(cabling.tube, tube);
680 chMap[chan] = dummy_card.
tubeNumber(layer, tube);
682 msg << MSG::VERBOSE <<
"legacyHedgehogCard() -- Channel "
683 << chan <<
" mapped to " << layer <<
", " << tube <<
endmsg;
685 return std::make_unique<MdtMezzanineCard>(chMap, 4, mezzType);
692 msg << MSG::VERBOSE <<
"Assign local tube mapping from " << (*card)
694 <<
"to connect " << cabling <<
" tubeZero: " << tubeZero <<
endmsg;
695 const int stationName = cabling.stationIndex;
696 const int stationEta = std::abs(cabling.eta);
698 for (
size_t chan = 0; chan < chMap.size(); ++chan) {
700 int layer{0}, tube{0};
701 if (layerZero == 1) {
711 if ((chanZero == 5 && stationName == 7 && stationEta == 3) &&
712 ((card->
id() > 40 && localchan % 2 == 0) ||
713 (card->
id() < 40 && localchan < 3)))
721 if (!locTubeLay.isValid || !zeroTubeLay.isValid)
724 tube = (
static_cast<int>(locTubeLay.tube) -
725 static_cast<int>(zeroTubeLay.tube) + tubeZero);
728 msg << MSG::VERBOSE <<
"legacyHedgehogCard() -- Channel " << chan
729 <<
" mapped to " << layer <<
", " << tube
730 <<
" locTube: " <<
static_cast<int>(locTubeLay.tube)
731 <<
" zeroTubeLay: " <<
static_cast<int>(zeroTubeLay.tube)
736 cabling.tube = std::min(cabling.tube, tube);
739 std::unique_ptr<MdtMezzanineCard> to_ret =
740 std::make_unique<MdtMezzanineCard>(chMap, card->
numTubeLayers(),
742 const uint8_t tubeZeroOff = (cabling.tube - 1) % to_ret->numTubesPerLayer();
746 for (
size_t chan = 0; chan < chMap.size(); ++chan) {
748 OfflineCh tube_lay = to_ret->offlineTube(chan,
msg);
749 if (!tube_lay.isValid)
751 uint8_t tubeNumber = tube_lay.tube + tubeZeroOff + 1;
752 chMap[chan] = card->
tubeNumber(tube_lay.layer, tubeNumber);
755 msg << MSG::VERBOSE <<
"Final mapping " << cabling <<
endmsg;
757 return std::make_unique<MdtMezzanineCard>(chMap, card->
numTubeLayers(),
constexpr std::array< T, N > make_array(const T &def_val)
Helper function to initialize in-place arrays with non-zero values.
MuonMDT_CablingMap::MezzCardPtr MezzCardPtr
This is a "hash" representation of an Identifier.
void show() const
Print out in hex form.
static constexpr int maxNTubesPerLayer
The maxNTubesPerLayer represents the absolute maximum of tubes which are built into a single multilay...
MdtMezzanineCard - Helper struct to represent the structure of a mezzanine card in a consistent way E...
static constexpr uint8_t NOTSET
bool checkConsistency(MsgStream &msg) const
checks whether the tdc mapping is complete.
OfflineCh offlineTube(uint8_t tdc, MsgStream &msg) const
uint8_t numTubesPerLayer() const
returns the number of tubes per layer;
uint8_t id() const
returns mezzanine database identifier
std::array< uint8_t, 24 > Mapping
uint8_t numTubeLayers() const
returns the number of layers
uint8_t tubeNumber(uint8_t tubeLay, uint8_t tube) const
returns the tube number
bool offlineId(MdtCablingData &cabling_data, MsgStream &log) const
retrieve the full information
unsigned int csmNumOnChamber(const CablingData &map_data, MsgStream &log) const
Returns whether the channel belongs to the first or second mounted CSM card.
ROBToChamberMap m_ROBToMultiLayer
map returning a detector element hashes associated with a given ROD
const ListOfROB & getAllROBId() const
return the ROD id of a given chamber
MezzCardPtr getHedgeHogMapping(uint8_t mezzCardId) const
std::vector< MdtTdcOnlSorter > TdcOnlSet
OnlToOffMap m_toOfflineConv
ChamberToROBMap m_chamberToROB
map returning the RODid for a given chamber ID
const OnlToOffMap & getOnlineConvMap() const
Returns the map to convert the online -> offline identifiers.
const OffToOnlMap & getOfflineConvMap() const
Returns hte map to convert the offline -> online identifiers.
std::map< MdtCablingOffData, MdtOffChModule > OffToOnlMap
OffToOnlMap m_toOnlineConv
MdtCablingData CablingData
bool getOnlineId(CablingData &cabling_data, MsgStream &log) const
return the online id given the offline id
bool addMezanineLayout(std::unique_ptr< MdtMezzanineCard > card, MsgStream &log)
Adds a new mezzanine card mapping.
bool m_2CSM_cham
Switch to check whether the layout has chambers with 2 CSM chips.
const MdtIdHelper * m_mdtIdHelper
Pointer to the MdtIdHelper.
bool getOfflineId(CablingData &cabling_data, MsgStream &log) const
return the offline id given the online id
ChamberToROBMap m_multilayerToROB
map raturning the RODid for a given multi layer ID
std::vector< uint32_t > ListOfROB
bool addChamberToROBMap(const CablingData &cabling_data, MsgStream &log)
private function to add a chamber to the ROD map
uint32_t getROBId(const IdentifierHash &stationCode, MsgStream &log) const
return the ROD id of a given chamber, given the hash id
std::vector< IdentifierHash > getMultiLayerHashVec(const std::vector< uint32_t > &ROBId_list, MsgStream &log) const
return a vector of HashId lists for a given list of ROD's
std::set< MdtTdcOffSorter, std::less<> > TdcOffSet
bool convert(const CablingData &cabling_data, Identifier &id, bool check_valid=true) const
converts the cabling data into an identifier.
bool addMezzanine(CablingData cabling_data, DataSource source, MsgStream &log)
Add a new fully configured mezzanine card.
bool getStationCode(const CablingData &map_data, IdentifierHash &mdtHashId, MsgStream &log) const
Transforms the identifier to an IdentifierHash corresponding to the module.
MezzCardPtr legacyHedgehogCard(CablingData &cabling, MsgStream &msg) const
In the legacy data format several transformations on the hedgehog layout were applied during the fina...
MdtMezzanineCard::MezzCardPtr MezzCardPtr
bool addMezzanineLine(const int type, const int layer, const int sequence, MsgStream &log)
Add a new line describing a mezzanine type.
bool finalize_init(MsgStream &log)
std::vector< std::unique_ptr< MdtTdcMap > > m_tdcs
std::map< MdtCablingOnData, MdtTdcModule > OnlToOffMap
ListOfROB m_listOfROB
full list of ROBs
bool has2CsmML() const
Returns if the cabling map has found multilayers connected to 2 CSM cards.
bool getMultiLayerCode(const CablingData &map_data, Identifier &multiLayer, IdentifierHash &mdtHashId, MsgStream &log) const
Transforms the identifier to an IdentifierHash corresponding to the multilayer In this case,...
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)
uint8_t tdcId
Mezzanine type.
uint8_t mezzanine_type
Tube number in the layer.
int tube
Layer inside the multilayer.
uint8_t channelId
Identifier of the corresponding tdc.
Split the offline part of the cabling apart to use it later for sorting.
int8_t & multilayer
Phi sector of the MDT station.
int8_t & eta
Station of the chamber (i.e, BIL,BIS,etc.)
int8_t & phi
Eta of the MDT station.
uint8_t & subdetectorId
CSM number.
Helper struct to pipe the result from the tdc -> offline channel translation.
Helper struct to search through the std::set if a conversion from offline -> online is needed.
Helper struct to search through the std::set if a conversion from online -> offline is needed.
Helper struct to group the Mezzanine cards mounted on each multilayer The object provides the followi...
TdcOffSet cards
Mezzanine cards mounted on the chamber.
std::array< MdtCablingOnData, 2 > csm
The up to 2 CSMs to which the cards are connected.
#define THROW_EXCEPTION(MESSAGE)
std::string number(const double &d, const std::string &s)