ATLAS Offline Software
Loading...
Searching...
No Matches
StripClusteringTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7
8#include <Acts/Clusterization/Clusterization.hpp>
9
13#include <TrkSurfaces/Surface.h>
14
15#include <algorithm>
16#include <stdexcept>
17
18
19namespace ActsTrk {
20constexpr double ONE_TWELFTH = 1./12.;
21constexpr float oneStripSF = 1.1025;
22constexpr float twoStripSF = 0.0729;
23
24 // Required by ACTS clusterization
25static
26int getCellColumn(const StripClusteringTool::Cell& cell)
27{
28 return cell.index;
29}
30
31// Required by ACTS clusterization
32static inline void clusterReserve(StripClusteringTool::Cluster& cl,
33 std::size_t n)
34{
35 cl.ids.reserve(n);
36}
37
38// Required by ACTS clusterization
39static
40void clusterAddCell(StripClusteringTool::Cluster& cl, const StripClusteringTool::Cell& cell)
41{
42 cl.ids.push_back(cell.id.get_compact());
43 if (cl.ids.size() < (sizeof(cl.hitsInThirdTimeBin) * 8)) {
44 cl.hitsInThirdTimeBin |= cell.timeBits.test(0) << cl.ids.size();
45 }
46}
47
49 const std::string& type, const std::string& name, const IInterface* parent)
50 : base_class(type,name,parent)
51{
52}
53
55{
56 ATH_MSG_DEBUG("Initializing " << name() << "...");
57
64
65
66 ATH_CHECK(m_conditionsTool.retrieve(DisableTool{!m_stripDetElStatus.empty()} ));
67 ATH_CHECK(m_lorentzAngleTool.retrieve());
69
70 ATH_CHECK(m_stripDetElStatus.initialize(not m_stripDetElStatus.empty()));
71 ATH_CHECK(m_stripDetEleCollKey.initialize());
72
73 ATH_CHECK( detStore()->retrieve(m_stripID, "SCT_ID") );
74
75 return StatusCode::SUCCESS;
76}
77
79{
80 for (size_t i = 0; i < m_timeBinStr.size(); i++) {
81 if (i >= 3) {
82 ATH_MSG_WARNING("Time bin string has excess characters");
83 break;
84 }
85 switch (std::toupper(m_timeBinStr[i])) {
86 case 'X': m_timeBinBits[i] = -1; break;
87 case '0': m_timeBinBits[i] = 0; break;
88 case '1': m_timeBinBits[i] = 1; break;
89 default:
90 ATH_MSG_FATAL("Invalid time bin string: " << m_timeBinStr);
91 return StatusCode::FAILURE;
92 }
93 }
94 return StatusCode::SUCCESS;
95}
96
97StatusCode
98StripClusteringTool::clusterize(const EventContext& ctx,
99 const RawDataCollection& RDOs,
100 const InDet::SiDetectorElementStatus& stripDetElStatus,
101 const InDetDD::SiDetectorElement& element,
102 Acts::Ccl::ClusteringData& data,
103 std::vector<typename IStripClusteringTool::ClusterCollection>& collection) const
104{
105 IdentifierHash idHash = RDOs.identifyHash();
106 // At least an empty cluster collection needs to be always added because the
107 // assumption is that there is one element per element RawDataCollection.
108 collection.emplace_back();
109 bool goodModule = true;
110 if (m_checkBadModules.value()) {
111 goodModule = stripDetElStatus.isGood(idHash);
112 }
113
115 m_checkBadModules.value() && !m_stripDetElStatus.empty(),
116 stripDetElStatus.isGood(idHash), m_conditionsTool->isGood(idHash));
117
118 if (!goodModule) {
119 ATH_MSG_DEBUG("Strip module failed status check");
120 return StatusCode::SUCCESS;
121 }
122
123 // If more than a certain number of RDOs set module to bad
124 // in this case we skip clusterization
125 if (m_maxFiredStrips != 0u) {
126 unsigned int nFiredStrips = 0u;
127 for (const SCT_RDORawData* rdo : RDOs) {
128 nFiredStrips += rdo->getGroupSize();
129 }
130 if (nFiredStrips > m_maxFiredStrips)
131 return StatusCode::SUCCESS;
132 }
133
134 std::optional<std::pair<typename IStripClusteringTool::CellCollection,bool>> unpckd
135 = unpackRDOs(ctx, RDOs, stripDetElStatus, element);
136
137 if (not unpckd.has_value()) {
138 ATH_MSG_FATAL("Error encountered while unpacking strip RDOs!");
139 return StatusCode::FAILURE;
140 }
141
142 auto& [cells, badStripOnModule] = *unpckd;
143 // Bad strips on a module invalidates the hitsInThirdTimeBin word.
144 // Therefore set it to 0 if that's the case.
145 // We are currently not using this, but keeping it here should we need it in the future
146
147 Acts::Ccl::createClusters<CellCollection, typename IStripClusteringTool::ClusterCollection, 1>(data, cells, collection.back());
148
149 return StatusCode::SUCCESS;
150}
151
152
153StatusCode
154StripClusteringTool::makeClusters(const EventContext& ctx,
156 const InDetDD::SiDetectorElement& element,
157 typename ClusterContainer::iterator itrContainer) const
158{
159 const IdentifierHash idHash = element.identifyHash();
160 double lorentzShift = m_lorentzAngleTool->getLorentzShift(idHash, ctx);
161
162 const InDetDD::SiDetectorDesign& design = element.design();
163 // get the pitch, this will be the local covariance for the cluster
164
165 assert((not m_isITk) || element.isBarrel() || dynamic_cast<const InDetDD::StripStereoAnnulusDesign*>(&element.design()) !=nullptr);
166 float pitch = (element.isBarrel() or (not m_isITk))
167 ? design.phiPitch()
168 : static_cast<const InDetDD::StripStereoAnnulusDesign&>(element.design()).phiPitchPhi();
169 Eigen::Matrix<float,1,1> localCov(pitch * pitch * ONE_TWELFTH);
170
171 for (typename IStripClusteringTool::Cluster& cl : clusters) {
172 try {
173 xAOD::StripCluster *xaodCluster = *itrContainer;
175 lorentzShift,
176 localCov,
177 *m_stripID,
178 element,
179 design,
180 *xaodCluster));
181 ++itrContainer;
182 } catch (const std::exception& e) {
183 ATH_MSG_FATAL("Exception thrown while creating xAOD::StripCluster:"
184 << e.what());
185 ATH_MSG_FATAL("Detector Element identifier: " << element.identify());
186 ATH_MSG_FATAL("Strip Identifiers in cluster:");
187 for (const auto& id : cl.ids)
188 ATH_MSG_FATAL(" " << id);
189 return StatusCode::FAILURE;
190 }
191 }
192
193 return StatusCode::SUCCESS;
194}
195
196static
197std::pair<
198 Eigen::Matrix<float,1,1>,
199 Eigen::Matrix<float,3,1>>
200computePosition(const StripClusteringTool::Cluster& cluster,
201 std::size_t size,
202 double lorentzShift,
203 const IStripClusteringTool::IDHelper& stripID,
204 const InDetDD::SiDetectorElement& element,
205 const InDetDD::SiDetectorDesign& design,
206 bool isITk )
207{
208
209 Identifier ids_front(cluster.ids.front());
210 Identifier ids_back(cluster.ids.back());
211 InDetDD::SiCellId frontId = stripID.strip(ids_front);
212 InDetDD::SiLocalPosition pos = design.localPositionOfCell(frontId);
213 if (size > 1) {
214 InDetDD::SiCellId backId = stripID.strip(ids_back);
216 design.localPositionOfCell(backId);
217 pos = 0.5 * (pos + backPos);
218 }
219
220 // update the xPhi position
221 pos.xPhi( pos.xPhi() + lorentzShift );
222 Eigen::Matrix<float,3,1> posG(element.surface().localToGlobal(pos).cast<float>());
223
224 if ((not element.isBarrel()) and isITk) {
225 assert(dynamic_cast<const InDetDD::StripStereoAnnulusDesign*>(&design) != nullptr);
226 const InDetDD::StripStereoAnnulusDesign& annulusDesign =
227 static_cast<const InDetDD::StripStereoAnnulusDesign&>
228 (design);
229 pos = annulusDesign.localPositionOfCellPC(element.cellIdOfPosition(pos));
230 }
231
232 return std::make_pair(Eigen::Matrix<float,1,1>(pos.xPhi()),
233 std::move(posG));
234}
235
236
237// N.B. the cluster is added to the container
238StatusCode
240 double lorentzShift,
241 Eigen::Matrix<float,1,1>& localCov,
242 const StripID& stripID,
243 const InDetDD::SiDetectorElement& element,
244 const InDetDD::SiDetectorDesign& design,
245 xAOD::StripCluster& cl) const
246{
247 std::size_t size = cluster.ids.size();
248
249 auto [localPos, globalPos]
250 = computePosition(cluster, size, lorentzShift, stripID, element, design, m_isITk);
251
252 // For Strip Clusters the identifier is taken from the front rod list object
253 // This is the same strategy used in Athena:
254 // Since clusterId is arbitary (it only needs to be unique) just use ID of first strip
255 // For strip Cluster it has been found that "identifierOfPosition" does not produces unique values
256
257
258 // If requiring broad errors, use the cluster size as error -
259 // TODO use SiWidth to get the right cluster size as I'm assuming equal strip pitch
260
261 if (m_errorStrategy == 1) {// use width
262
263 localCov *= size*size;
264
265 } else if (m_errorStrategy == 2) { //use tuned error as function of size
266
267 if (size == 1)
268 localCov *= oneStripSF;
269 else if (size == 2)
270 localCov *= twoStripSF*size*size;
271 else
272 localCov *= size*size;
273
274 }
275
276 cl.setMeasurement<1>(element.identifyHash(), localPos, localCov);
277 cl.setIdentifier( cluster.ids.front() );
278
279 // Do I really need the global position in fast tracking?
280 cl.globalPosition() = globalPos;
281
282 cl.setChannelsInPhi(size);
283 cl.setRDOlist(std::move(cluster.ids));
284
285 return StatusCode::SUCCESS;
286}
287
288
289bool StripClusteringTool::passTiming(const std::bitset<3>& timePattern) const {
290 // Convert the given timebin to a bit set and test each bit
291 // if bit is -1 (i.e. X) it always passes, other wise require exact match of 0/1
292 // N.B bitset has opposite order to the bit pattern we define
293 if (m_timeBinBits[0] != -1 and timePattern.test(2) != static_cast<bool>(m_timeBinBits[0])) return false;
294 if (m_timeBinBits[1] != -1 and timePattern.test(1) != static_cast<bool>(m_timeBinBits[1])) return false;
295 if (m_timeBinBits[2] != -1 and timePattern.test(0) != static_cast<bool>(m_timeBinBits[2])) return false;
296 return true;
297}
298
299
300bool StripClusteringTool::isBadStrip(const EventContext& ctx,
301 const InDet::SiDetectorElementStatus *stripDetElStatus,
302 const StripID& stripID,
303 IdentifierHash waferHash,
304 Identifier stripId) const
305{
306 if (stripDetElStatus) {
307 const int strip_i{stripID.strip(stripId)};
309 stripDetElStatus,
310 stripDetElStatus->isCellGood(waferHash.value(), strip_i),
312 return not stripDetElStatus->isCellGood(waferHash.value(), strip_i) ;
313 }
314 return not m_conditionsTool->isGood(stripId, InDetConditions::SCT_STRIP, ctx);
315}
316
317
318std::optional<std::pair<typename IStripClusteringTool::CellCollection, bool>>
319StripClusteringTool::unpackRDOs(const EventContext& ctx,
320 const RawDataCollection& RDOs,
321 const InDet::SiDetectorElementStatus& stripDetElStatus,
322 const InDetDD::SiDetectorElement& element) const
323{
324 const InDetDD::SiDetectorDesign& design = element.design();
325
326 CellCollection cells;
327 // reserve memory. number evaluated on ttbar pu200
328 cells.reserve(60);
329 bool badStripOnModule{false};
330 //Check type in debug build otherwise assume it is correct
331 assert(dynamic_cast<const InDetDD::SCT_ModuleSideDesign*>(&design)!=nullptr);
332 std::size_t ncells = static_cast<size_t>(static_cast<const InDetDD::SCT_ModuleSideDesign&>(design).cells());
333
334 // Simple single-entry cache
335 Identifier::value_type waferId_compact_cache = 0;
336 IdentifierHash waferHash_cache(0);
337 bool cache_valid = false;
338
339 for (const StripRDORawData * raw : RDOs) {
340
341 //Check type in debug build otherwise assume it is correct
342 assert(static_cast<const SCT3_RawData*>(raw)!=nullptr);
343 const SCT3_RawData* raw3 = static_cast<const SCT3_RawData*>(raw);
344
345 std::bitset<3> timePattern(raw3->getTimeBin());
346 if (!passTiming(timePattern)) {
347 ATH_MSG_DEBUG("Strip failed timing check");
348 continue;
349 }
350
351 Identifier firstStripId = raw->identify();
352 Identifier waferId = m_stripID->wafer_id(firstStripId);
353
354 Identifier::value_type waferId_compact = waferId.get_compact();
355
356
357 // Check cache - will be invalid when switching wafer groups
358 if (!cache_valid || waferId_compact != waferId_compact_cache) {
359 waferId_compact_cache = waferId_compact;
360 waferHash_cache = m_stripID->wafer_hash(waferId);
361 cache_valid = true;
362 }
363
364 std::size_t iFirstStrip = static_cast<size_t>(m_stripID->strip(firstStripId));
365
366 std::size_t iMaxStrip = std::min(
367 iFirstStrip + raw->getGroupSize(),
368 ncells
369 );
370
371 for (size_t i = iFirstStrip; i < iMaxStrip; i++) {
372 Identifier stripIdent = m_stripID->strip_id(waferId, i);
373 if (isBadStrip(ctx, &stripDetElStatus, *m_stripID, waferHash_cache, stripIdent)) {
374 // Bad strip, throw it out to minimize useless work.
375 ATH_MSG_DEBUG("Bad strip encountered:" << stripIdent
376 << ", wafer is: " << waferId);
377 badStripOnModule = true;
378 } else {
379 // Good strip!
380 cells.emplace_back(i, stripIdent, std::move(timePattern));
381 }
382 }
383 }
384
385 return std::make_pair(std::move(cells), badStripOnModule);
386}
387
388} // namespace ActsTrk
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
#define VALIDATE_STATUS_ARRAY(use_info, info_val, summary_val)
std::vector< Cluster > ClusterCollection
Gaudi::Property< bool > m_isITk
ToolHandle< IInDetConditionsTool > m_conditionsTool
Gaudi::Property< unsigned int > m_maxFiredStrips
Gaudi::Property< bool > m_checkBadModules
bool passTiming(const std::bitset< 3 > &timePattern) const
virtual StatusCode initialize() override
bool isBadStrip(const EventContext &ctx, const InDet::SiDetectorElementStatus *sctDetElStatus, const StripID &idHelper, IdentifierHash waferHash, Identifier stripId) const
StripClusteringTool(const std::string &type, const std::string &name, const IInterface *parent)
ToolHandle< ISiLorentzAngleTool > m_lorentzAngleTool
StatusCode makeCluster(StripClusteringTool::Cluster &cluster, double LorentzShift, Eigen::Matrix< float, 1, 1 > &localCov, const StripID &stripID, const InDetDD::SiDetectorElement &element, const InDetDD::SiDetectorDesign &design, xAOD::StripCluster &container) const
virtual StatusCode clusterize(const EventContext &ctx, const InDetRawDataCollection< StripRDORawData > &RDOs, const InDet::SiDetectorElementStatus &stripDetElStatus, const InDetDD::SiDetectorElement &element, Acts::Ccl::ClusteringData &data, std::vector< typename IStripClusteringTool::ClusterCollection > &collection) const override
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_stripDetEleCollKey
virtual StatusCode makeClusters(const EventContext &ctx, typename IStripClusteringTool::ClusterCollection &cluster, const InDetDD::SiDetectorElement &element, typename ClusterContainer::iterator itrContainer) const override
Gaudi::Property< unsigned int > m_errorStrategy
SG::ReadHandleKey< InDet::SiDetectorElementStatus > m_stripDetElStatus
std::optional< std::pair< typename IStripClusteringTool::CellCollection, bool > > unpackRDOs(const EventContext &ctx, const RawDataCollection &RDOs, const InDet::SiDetectorElementStatus &stripDetElStatus, const InDetDD::SiDetectorElement &element) const
This is a "hash" representation of an Identifier.
value_type value() const
value_type get_compact() const
Get the compact id.
virtual SiLocalPosition localPositionOfCell(const SiCellId &cellId) const =0
readout or diode id -> position.
virtual double phiPitch() const =0
Pitch in phi direction.
Base class for the SCT module side design, extended by the Forward and Barrel module design.
int cells() const
number of readout stips within module side:
Identifier for the strip or pixel cell.
Definition SiCellId.h:29
Base class for the detector design classes for Pixel and SCT.
Class to hold geometrical description of a silicon detector element.
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
Class to represent a position in the natural frame of a silicon sensor, for Pixel and SCT For Pixel: ...
SiCellId cellIdOfPosition(const Amg::Vector2D &localPos) const
As in previous method but returns SiCellId.
virtual IdentifierHash identifyHash() const override final
identifier hash (inline)
virtual Identifier identify() const override final
identifier of this detector element (inline)
Trk::Surface & surface()
Element Surface.
double phiPitchPhi(const SiLocalPosition &localPosition) const
SiLocalPosition localPositionOfCellPC(const SiCellId &cellId) const
This is for debugging only.
bool isCellGood(IdentifierHash hash, unsigned short cell_i) const
bool isGood(IdentifierHash hash) const
int getTimeBin() const
int strip(const Identifier &id) const
Definition SCT_ID.h:717
virtual void localToGlobal(const Amg::Vector2D &locp, const Amg::Vector3D &mom, Amg::Vector3D &glob) const =0
Specified by each surface type: LocalToGlobal method without dynamic memory allocation.
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
constexpr float oneStripSF
static std::pair< Eigen::Matrix< float, 1, 1 >, Eigen::Matrix< float, 3, 1 > > computePosition(const StripClusteringTool::Cluster &cluster, std::size_t size, double lorentzShift, const IStripClusteringTool::IDHelper &stripID, const InDetDD::SiDetectorElement &element, const InDetDD::SiDetectorDesign &design, bool isITk)
static void clusterAddCell(PixelClusteringTool::Cluster &cl, const PixelClusteringTool::Cell &cell)
constexpr float twoStripSF
constexpr double ONE_TWELFTH
static int getCellColumn(const typename PixelClusteringTool::Cell &cell)
static void clusterReserve(PixelClusteringTool::Cluster &cl, std::size_t n)
StripCluster_v1 StripCluster
Define the version of the strip cluster class.