ATLAS Offline Software
Loading...
Searching...
No Matches
ITkPixelCablingAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
13
14//package includes
15#include "ITkPixelCablingAlg.h"
16
17//indet includes
22
23
24//Athena includes
25#include "Identifier/Identifier.h"
29
30
31
32// Gaudi include
33#include "GaudiKernel/EventIDRange.h"
34
35
36//STL
37#include <iostream>
38#include <fstream>
39
40// CREST
41#include <chai/Database.h>
42
43//json
44#include <nlohmann/json.hpp>
45
46
47
48// Constructor
49ITkPixelCablingAlg::ITkPixelCablingAlg(const std::string& name, ISvcLocator* pSvcLocator):
50 AthCondAlgorithm(name, pSvcLocator)
51{
52}
53
54//
55StatusCode
57 // ITkPixelID
58 ATH_CHECK(detStore()->retrieve(m_idHelper, "PixelID"));
59 // det manager
60 if (m_useTestCabling) ATH_CHECK(detStore()->retrieve(m_detManager, "ITkPixel"));
61 // Read Cond Key
62 ATH_CHECK( m_readKey.initialize() );
63 // Write Cond Handle
64 ATH_CHECK(m_writeKey.initialize());
65
66 return StatusCode::SUCCESS;
67}
68
69
70//
71StatusCode
72ITkPixelCablingAlg::execute(const EventContext& ctx) const {
73 // Write Cond Handle
75 if (writeHandle.isValid()) {
76 ATH_MSG_DEBUG("CondHandle " << writeHandle.fullKey() << " is already valid."
77 << ". In theory this should not be called, but may happen"
78 << " if multiple concurrent events are being processed out of order.");
79 return StatusCode::SUCCESS;
80 }
82 const AthenaAttributeList* attr{*readHandle};
83
84 if (attr==nullptr) {
85 ATH_MSG_ERROR("Failed to retrieve AthenaAttributeList with key " << m_readKey.key());
86 return StatusCode::FAILURE;
87 }
88 const std::string& pl = (*attr)["cabling"].data<std::string>();
89
90 // Construct the output Cond Object and fill it in
91 std::unique_ptr<ITkPixelCablingData> pCabling = std::make_unique<ITkPixelCablingData>();
92
93 //For development purposes, generate a dummy cabling structure, using the existing
94 //offline IDs and dummy online ones. It's problematic to deal with quads easily, as
95 //they have one offline ID, but up to 4 online IDs. If there will be virtual elinks
96 //for merged quads or if there's no data merging, the situation is not mappable for
97 //the encoding offline -> online map. Once could at most map to certain bits that
98 //would be shared between the 4 online IDs. In the decoding direction, the
99 //online->offline will be always mappable, although it would be degenerate mapping.
100 if (m_useTestCabling){
101 ATH_MSG_DEBUG("Using test cabling generated with ITkPixelCablingAlg::generateTestCabling(...)");
103 pCabling->print();
104 if (writeHandle.record(EventIDRange(IOVInfiniteRange::infiniteRunLB()), std::move(pCabling)).isFailure()) {
105 return StatusCode::FAILURE;
106 }
107
108 return StatusCode::SUCCESS;
109 }
110
111 ATH_CHECK(fillFromCREST(pCabling, pl));
112 const int numEntries = pCabling->size();
113 ATH_MSG_DEBUG(numEntries << " entries were made to the identifier map.");
114
115 // Define validity of the output cond object and record it
116 const EventIDBase start{EventIDBase::UNDEFNUM, EventIDBase::UNDEFEVT, 0, 0, EventIDBase::UNDEFNUM, EventIDBase::UNDEFNUM};
117 const EventIDBase stop{EventIDBase::UNDEFNUM, EventIDBase::UNDEFEVT, EventIDBase::UNDEFNUM-1, EventIDBase::UNDEFNUM-1, EventIDBase::UNDEFNUM, EventIDBase::UNDEFNUM};
118 const EventIDRange rangeW{start, stop};
119 if (writeHandle.record(rangeW, std::move(pCabling)).isFailure()) {
120 ATH_MSG_FATAL("Could not record ITkPixelCablingData " << writeHandle.key()
121 << " with EventRange " << rangeW
122 << " into Conditions Store");
123 return StatusCode::FAILURE;
124 }
125 ATH_MSG_VERBOSE("recorded new conditions data object " << writeHandle.key() << " with range " << rangeW << " into Conditions Store");
126 return (numEntries==0) ? (StatusCode::FAILURE) : (StatusCode::SUCCESS);
127}
128
129StatusCode ITkPixelCablingAlg::generateTestCabling(std::unique_ptr<ITkPixelCablingData>& cabling) const {
130 //We'll loop over all known hashes, and create a sensible cabling situation
131 //for testing purposes, create online ID by shifting the wafer ID by two bits, allowing
132 //to accommodate the non-merged quads with 4 online links vs. one offline entity.
133 //What's used as the online "base" (32 bit) is just the offline ID (64bit) >> 32.
134 //Lowest two bits are always 0 in the base - in fact, at least 2 bytes are. Fine for testing.
135
136 std::unordered_set<uint32_t> seen;
137
138 for (size_t hash = 0; hash < m_idHelper->wafer_hash_max(); hash++){
139 Identifier id = m_idHelper->wafer_id(hash);
140 uint32_t onID = (id.get_identifier32().get_compact());
141
142 const InDetDD::SiDetectorElement *element = m_detManager->getDetectorElement(id);
143 const InDetDD::PixelModuleDesign *p_design = static_cast<const InDetDD::PixelModuleDesign *>(&element->design());
144
145 //a dummy sourceID - has nothing to do with reality, and is intended
146 //for testing purposes only
147
148 uint32_t sourceID = std::abs(m_idHelper->barrel_ec(id)) << 26 | m_idHelper->layer_disk(id) << 20;
149 if (seen.insert(sourceID).second) cabling->addSourceID(sourceID);
150
152 ITkPixelCabling::TransformType moduleTransform;
153 if (p_design->numberOfCircuits() == 4){
154 //it's a quad
155
156 //Let's make the entire layer 1 and 2 non-merged.
157 //We can experiment with this, but we're also after
158 //a proof-of-principle here.
159 if (m_idHelper->barrel_ec(id) == 0 && (m_idHelper->layer_disk(id) == 1 || m_idHelper->layer_disk(id) == 2)){
160 //Non-merged quad has 4 online IDs mappend onto 1 offline,
161 //differentiated by 2-bit chip ID
164 cabling->addEntryOnOff(onID | 0b00, ITkPixelCabling::ModuleInfo(id, moduleType, moduleTransform));
165 cabling->addEntryOnOff(onID | 0b01, ITkPixelCabling::ModuleInfo(id, moduleType, moduleTransform));
166 cabling->addEntryOnOff(onID | 0b10, ITkPixelCabling::ModuleInfo(id, moduleType, moduleTransform));
167 cabling->addEntryOnOff(onID | 0b11, ITkPixelCabling::ModuleInfo(id, moduleType, moduleTransform));
168
169 }
170 else{
171 //Merged quads have 1:1 online:offline correspondence.
172 //Don't need to invent any substructure, but keep it
173 //consistent with the quads
176 cabling->addEntryOnOff(onID, ITkPixelCabling::ModuleInfo(id, moduleType, moduleTransform));
177 }
178
179 //We can also fill in the offline->online map
180 //Were are creating the "base" online ID, i. e. without the chip ID
181 cabling->addEntryOffOn(id, ITkPixelCabling::ModuleInfo<ITkPixelOnlineId>(onID, moduleType, moduleTransform));
182
183
184 //Fill in also the updated ROB-structure-respecting map with some dummy values
185 cabling->addEntryOffOn((onID >> 8) | 0x00000000, ITkPixelOnlineId(sourceID, (onID >> 8) | 0x00000000));
186 cabling->addEntryOffOn((onID >> 8) | 0x40000000, ITkPixelOnlineId(sourceID, (onID >> 8) | 0x40000000));
187 cabling->addEntryOffOn((onID >> 8) | 0x80000000, ITkPixelOnlineId(sourceID, (onID >> 8) | 0x80000000));
188 cabling->addEntryOffOn((onID >> 8) | 0xC0000000, ITkPixelOnlineId(sourceID, (onID >> 8) | 0xC0000000));
189 cabling->addTransformType(onID, ITkPixelCabling::TransformType::NominalQuad);
190
191 }
192 else {
193
194 //All triplets map 1:1 to chips. Keeping the online
195 //"base" ID consistently shifted - we're dealing with chip 00
198 cabling->addEntryOnOff(onID, ITkPixelCabling::ModuleInfo(id, moduleType, moduleTransform));
199
200 //We can also fill in the offline->online map
201 //Were are creating the "base" online ID, i. e. without the chip ID
202 cabling->addEntryOffOn(id, ITkPixelCabling::ModuleInfo<ITkPixelOnlineId>(onID, moduleType, moduleTransform));
203
204 //Fill in also the updated ROB-structure-respecting map with some dummy values
205 cabling->addEntryOffOn((onID >> 8), ITkPixelOnlineId(sourceID, onID >> 8));
206 if (m_idHelper->barrel_ec(id) == 0){
207 cabling->addTransformType(onID, ITkPixelCabling::TransformType::NominalIBTriplet);
208 }
209 else {
210 cabling->addTransformType(onID, ITkPixelCabling::TransformType::NominalIECTriplet);
211 }
212 }
213
214 }
215
216 return StatusCode::SUCCESS;
217}
218
219StatusCode ITkPixelCablingAlg::fillFromCREST(std::unique_ptr<ITkPixelCablingData>& cabling, const std::string& c) const {
220
221 // Remove Python bytes representation: b'...'
222 std::string s=c;
223 if (c.size() >= 3 &&
224 c.substr(0, 2) == "b'" &&
225 c.back() == '\''){
226 s = c.substr(2, c.size() - 3);
227 }
228 // Parse JSON
229 nlohmann::json config = nlohmann::json::parse(s);
230
231 std::unordered_set<uint32_t> seen;
232
233 for (const auto& entry : config) {
234
235 const uint32_t detectorResourceID = std::stoul(entry.at("DetectorResourceID").get<std::string>(), nullptr, 16);
236
237 const uint32_t trueDetectorResourceID = std::stoul(entry.at("TrueDetectorResourceID").get<std::string>(), nullptr, 16);
238
239 const uint32_t sourceID = std::stoul(entry.at("SourceID").get<std::string>(), nullptr, 16);
240
241 cabling->addEntryOffOn(detectorResourceID & ITkPixelCabling::OFFLINE_DRID_MASK, ITkPixelOnlineId(sourceID, detectorResourceID));
242
243 if (seen.insert(sourceID).second) cabling->addSourceID(sourceID);
244
245 uint64_t moduleID = (static_cast<uint64_t>(ITkPixelCabling::dridToModuleID(trueDetectorResourceID)) << 32);
246
247 Identifier id(static_cast<Identifier::value_type>(moduleID));
248 if (m_idHelper->barrel_ec(id) == 0 && m_idHelper->layer_disk(id) == 0) cabling->addTransformType(ITkPixelCabling::dridToModuleID(trueDetectorResourceID), ITkPixelCabling::TransformType::NominalIBTriplet);
249 else if (m_idHelper->barrel_ec(id) != 0 && (m_idHelper->layer_disk(id) == 0 || m_idHelper->layer_disk(id) == 1) ) cabling->addTransformType(ITkPixelCabling::dridToModuleID(trueDetectorResourceID), ITkPixelCabling::TransformType::NominalIECTriplet);
250 else cabling->addTransformType(ITkPixelCabling::dridToModuleID(trueDetectorResourceID), ITkPixelCabling::TransformType::NominalQuad);
251 ATH_MSG_DEBUG(std::hex << " key " << (detectorResourceID & ITkPixelCabling::OFFLINE_DRID_MASK) << " detectorResourceID " << detectorResourceID << " trueDetectorResourceID " << trueDetectorResourceID << " sourceID " << sourceID);
252 }
253
254 return StatusCode::SUCCESS;
255}
256
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_FATAL(x,...)
Fills an ITkPixelCablingData object and records it in Storegate.
This is an Identifier helper class for the Pixel subdetector.
const ServiceHandle< StoreGateSvc > & detStore() const
Base class for conditions algorithms.
An AttributeList represents a logical row of attributes in a metadata table.
static EventIDRange infiniteRunLB()
Produces an EventIDRange that is infinite in RunLumi and invalid in Time.
SG::WriteCondHandleKey< ITkPixelCablingData > m_writeKey
virtual StatusCode initialize() override
virtual StatusCode execute(const EventContext &ctx) const override
StatusCode fillFromCREST(std::unique_ptr< ITkPixelCablingData > &cabling, const std::string &c) const
SG::ReadCondHandleKey< AthenaAttributeList > m_readKey
const InDetDD::PixelDetectorManager * m_detManager
const PixelID * m_idHelper
StatusCode generateTestCabling(std::unique_ptr< ITkPixelCablingData > &cabling) const
ITkPixelCablingAlg(const std::string &name, ISvcLocator *svc)
Gaudi::Property< bool > m_useTestCabling
Class used to describe the design of a module (diode segmentation and readout scheme).
int numberOfCircuits() const
Total number of circuits:
Class to hold geometrical description of a silicon detector element.
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
const std::string & key() const
StatusCode record(const EventIDRange &range, T *t)
record handle, with explicit range DEPRECATED
const DataObjID & fullKey() const
uint32_t dridToModuleID(const uint32_t &drid)
static constexpr uint32_t OFFLINE_DRID_MASK
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())