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 // Write Cond Handle
62 ATH_CHECK(m_writeKey.initialize());
63
64 return StatusCode::SUCCESS;
65}
66
67
68//
69StatusCode
70ITkPixelCablingAlg::execute(const EventContext& ctx) const {
71 // Write Cond Handle
73 if (writeHandle.isValid()) {
74 ATH_MSG_DEBUG("CondHandle " << writeHandle.fullKey() << " is already valid."
75 << ". In theory this should not be called, but may happen"
76 << " if multiple concurrent events are being processed out of order.");
77 return StatusCode::SUCCESS;
78 }
79
80 // Construct the output Cond Object and fill it in
81 std::unique_ptr<ITkPixelCablingData> pCabling = std::make_unique<ITkPixelCablingData>();
82
83 //For development purposes, generate a dummy cabling structure, using the existing
84 //offline IDs and dummy online ones. It's problematic to deal with quads easily, as
85 //they have one offline ID, but up to 4 online IDs. If there will be virtual elinks
86 //for merged quads or if there's no data merging, the situation is not mappable for
87 //the encoding offline -> online map. Once could at most map to certain bits that
88 //would be shared between the 4 online IDs. In the decoding direction, the
89 //online->offline will be always mappable, although it would be degenerate mapping.
91 ATH_MSG_DEBUG("Using test cabling generated with ITkPixelCablingAlg::generateTestCabling(...)");
93 pCabling->print();
94 if (writeHandle.record(EventIDRange(IOVInfiniteRange::infiniteRunLB()), std::move(pCabling)).isFailure()) {
95 return StatusCode::FAILURE;
96 }
97
98 return StatusCode::SUCCESS;
99 }
100
101 ATH_CHECK(fillFromCREST(pCabling));
102 const int numEntries = pCabling->size();
103 ATH_MSG_DEBUG(numEntries << " entries were made to the identifier map.");
104
105 // Define validity of the output cond object and record it
106 const EventIDBase start{EventIDBase::UNDEFNUM, EventIDBase::UNDEFEVT, 0, 0, EventIDBase::UNDEFNUM, EventIDBase::UNDEFNUM};
107 const EventIDBase stop{EventIDBase::UNDEFNUM, EventIDBase::UNDEFEVT, EventIDBase::UNDEFNUM-1, EventIDBase::UNDEFNUM-1, EventIDBase::UNDEFNUM, EventIDBase::UNDEFNUM};
108 const EventIDRange rangeW{start, stop};
109 if (writeHandle.record(rangeW, std::move(pCabling)).isFailure()) {
110 ATH_MSG_FATAL("Could not record ITkPixelCablingData " << writeHandle.key()
111 << " with EventRange " << rangeW
112 << " into Conditions Store");
113 return StatusCode::FAILURE;
114 }
115 ATH_MSG_VERBOSE("recorded new conditions data object " << writeHandle.key() << " with range " << rangeW << " into Conditions Store");
116 return (numEntries==0) ? (StatusCode::FAILURE) : (StatusCode::SUCCESS);
117}
118
119StatusCode ITkPixelCablingAlg::generateTestCabling(std::unique_ptr<ITkPixelCablingData>& cabling) const {
120 //We'll loop over all known hashes, and create a sensible cabling situation
121 //for testing purposes, create online ID by shifting the wafer ID by two bits, allowing
122 //to accommodate the non-merged quads with 4 online links vs. one offline entity.
123 //What's used as the online "base" (32 bit) is just the offline ID (64bit) >> 32.
124 //Lowest two bits are always 0 in the base - in fact, at least 2 bytes are. Fine for testing.
125
126 std::unordered_set<uint32_t> seen;
127
128 for (size_t hash = 0; hash < m_idHelper->wafer_hash_max(); hash++){
129 Identifier id = m_idHelper->wafer_id(hash);
130 uint32_t onID = (id.get_identifier32().get_compact());
131
132 const InDetDD::SiDetectorElement *element = m_detManager->getDetectorElement(id);
133 const InDetDD::PixelModuleDesign *p_design = static_cast<const InDetDD::PixelModuleDesign *>(&element->design());
134
135 //a dummy sourceID - has nothing to do with reality, and is intended
136 //for testing purposes only
137
138 uint32_t sourceID = std::abs(m_idHelper->barrel_ec(id)) << 26 | m_idHelper->layer_disk(id) << 20;
139 if (seen.insert(sourceID).second) cabling->addSourceID(sourceID);
140
142 ITkPixelCabling::TransformType moduleTransform;
143 if (p_design->numberOfCircuits() == 4){
144 //it's a quad
145
146 //Let's make the entire layer 1 and 2 non-merged.
147 //We can experiment with this, but we're also after
148 //a proof-of-principle here.
149 if (m_idHelper->barrel_ec(id) == 0 && (m_idHelper->layer_disk(id) == 1 || m_idHelper->layer_disk(id) == 2)){
150 //Non-merged quad has 4 online IDs mappend onto 1 offline,
151 //differentiated by 2-bit chip ID
154 cabling->addEntryOnOff(onID | 0b00, ITkPixelCabling::ModuleInfo(id, moduleType, moduleTransform));
155 cabling->addEntryOnOff(onID | 0b01, ITkPixelCabling::ModuleInfo(id, moduleType, moduleTransform));
156 cabling->addEntryOnOff(onID | 0b10, ITkPixelCabling::ModuleInfo(id, moduleType, moduleTransform));
157 cabling->addEntryOnOff(onID | 0b11, ITkPixelCabling::ModuleInfo(id, moduleType, moduleTransform));
158
159 }
160 else{
161 //Merged quads have 1:1 online:offline correspondence.
162 //Don't need to invent any substructure, but keep it
163 //consistent with the quads
166 cabling->addEntryOnOff(onID, ITkPixelCabling::ModuleInfo(id, moduleType, moduleTransform));
167 }
168
169 //We can also fill in the offline->online map
170 //Were are creating the "base" online ID, i. e. without the chip ID
171 cabling->addEntryOffOn(id, ITkPixelCabling::ModuleInfo<ITkPixelOnlineId>(onID, moduleType, moduleTransform));
172
173
174 //Fill in also the updated ROB-structure-respecting map with some dummy values
175 cabling->addEntryOffOn((onID >> 8) | 0x00000000, ITkPixelOnlineId(sourceID, (onID >> 8) | 0x00000000));
176 cabling->addEntryOffOn((onID >> 8) | 0x40000000, ITkPixelOnlineId(sourceID, (onID >> 8) | 0x40000000));
177 cabling->addEntryOffOn((onID >> 8) | 0x80000000, ITkPixelOnlineId(sourceID, (onID >> 8) | 0x80000000));
178 cabling->addEntryOffOn((onID >> 8) | 0xC0000000, ITkPixelOnlineId(sourceID, (onID >> 8) | 0xC0000000));
179 cabling->addTransformType(onID, ITkPixelCabling::TransformType::NominalQuad);
180
181 }
182 else {
183
184 //All triplets map 1:1 to chips. Keeping the online
185 //"base" ID consistently shifted - we're dealing with chip 00
188 cabling->addEntryOnOff(onID, ITkPixelCabling::ModuleInfo(id, moduleType, moduleTransform));
189
190 //We can also fill in the offline->online map
191 //Were are creating the "base" online ID, i. e. without the chip ID
192 cabling->addEntryOffOn(id, ITkPixelCabling::ModuleInfo<ITkPixelOnlineId>(onID, moduleType, moduleTransform));
193
194 //Fill in also the updated ROB-structure-respecting map with some dummy values
195 cabling->addEntryOffOn((onID >> 8), ITkPixelOnlineId(sourceID, onID >> 8));
196 if (m_idHelper->barrel_ec(id) == 0){
197 cabling->addTransformType(onID, ITkPixelCabling::TransformType::NominalIBTriplet);
198 }
199 else {
200 cabling->addTransformType(onID, ITkPixelCabling::TransformType::NominalIECTriplet);
201 }
202 }
203
204 }
205
206 return StatusCode::SUCCESS;
207}
208
209StatusCode ITkPixelCablingAlg::fillFromCREST(std::unique_ptr<ITkPixelCablingData>& cabling) const {
210
211 chai::Database db(m_crestServer);
212 auto tag = db.getTag(m_crestTag);
213 auto [payload, since, until] = tag->getPayloadAt(m_crestTime);
214 auto config = payload.toJson();
215 //format the json file correctly, need to decode utf8 by hand...
216 if (config.contains("0")) {
217 config["sideAC"] = std::move(config["0"]);
218 config.erase("0");
219 }
220 //Clean and parse string elements inside 'sideAC'
221 if (config.contains("sideAC") && config["sideAC"].is_array()) {
222 for (auto& item : config["sideAC"]) {
223 if (item.is_string()) {
224 std::string str = item.get<std::string>();
225 // Strip leading b' and trailing '
226 if (str.rfind("b'", 0) == 0) {
227 str = str.substr(2, str.length() - 3);
228 }
229 // Remove backslashes
230 str.erase(std::remove(str.begin(), str.end(), '\\'), str.end());
231 // Parse cleaned string back using nlohmann::json
232 item = nlohmann::json::parse(str);
233 }
234 }
235 }
236 std::unordered_set<uint32_t> seen;
237
238 for (const auto& [side, groups] : config.items()) {
239
240 for (const auto& group : groups) {
241
242 for (const auto& entry : group) {
243
244 const uint32_t detectorResourceID = std::stoul(entry.at("DetectorResourceID").get<std::string>(), nullptr, 16);
245
246 const uint32_t trueDetectorResourceID = std::stoul(entry.at("TrueDetectorResourceID").get<std::string>(), nullptr, 16);
247
248 const uint32_t sourceID = std::stoul(entry.at("SourceID").get<std::string>(), nullptr, 16);
249
250 cabling->addEntryOffOn(detectorResourceID & ITkPixelCabling::OFFLINE_DRID_MASK, ITkPixelOnlineId(sourceID, detectorResourceID));
251
252 if (seen.insert(sourceID).second) cabling->addSourceID(sourceID);
253
254 uint64_t moduleID = (static_cast<uint64_t>(ITkPixelCabling::dridToModuleID(trueDetectorResourceID)) << 32);
255
256 Identifier id(static_cast<Identifier::value_type>(moduleID));
257 if (m_idHelper->barrel_ec(id) == 0 && m_idHelper->layer_disk(id) == 0) cabling->addTransformType(ITkPixelCabling::dridToModuleID(trueDetectorResourceID), ITkPixelCabling::TransformType::NominalIBTriplet);
258 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);
259 else cabling->addTransformType(ITkPixelCabling::dridToModuleID(trueDetectorResourceID), ITkPixelCabling::TransformType::NominalQuad);
260
261 ATH_MSG_DEBUG(std::hex << " key " << (detectorResourceID & ITkPixelCabling::OFFLINE_DRID_MASK) << " detectorResourceID " << detectorResourceID << " trueDetectorResourceID " << trueDetectorResourceID << " sourceID " << sourceID);
262 }
263 }
264 }
265
266 return StatusCode::SUCCESS;
267}
268
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(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.
static EventIDRange infiniteRunLB()
Produces an EventIDRange that is infinite in RunLumi and invalid in Time.
SG::WriteCondHandleKey< ITkPixelCablingData > m_writeKey
StatusCode fillFromCREST(std::unique_ptr< ITkPixelCablingData > &cabling) const
virtual StatusCode initialize() override
Gaudi::Property< std::string > m_crestServer
virtual StatusCode execute(const EventContext &ctx) const override
Gaudi::Property< uint64_t > m_crestTime
const InDetDD::PixelDetectorManager * m_detManager
const PixelID * m_idHelper
Gaudi::Property< std::string > m_crestTag
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())
DataModel_detail::iterator< DVL > remove(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, const T &value)
Specialization of remove for DataVector/List.