ATLAS Offline Software
Loading...
Searching...
No Matches
TotPixelClusterSplitter.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include "GaudiKernel/ServiceHandle.h"
10
12
15#include <algorithm> //minmax_element
16#include <tuple> //std::tuple
17
18InDet::TotPixelClusterSplitter::TotPixelClusterSplitter(const std::string & type, const std::string & name, const IInterface * parent) :
19 base_class(type, name, parent),
20 m_minPixels(3),
21 m_maxPixels(25)
22{
23}
24
26
27 ATH_CHECK(m_chargeDataKey.initialize());
28
29 return StatusCode::SUCCESS;
30}
31
33 return StatusCode::SUCCESS;
34}
35
36std::vector<InDet::PixelClusterParts>
38
39 std::vector<InDet::PixelClusterParts> Parts;
40
41 const std::vector<Identifier> & Rdos = OrigCluster.rdoList();
42 const unsigned int NumPixels = static_cast<unsigned int>(Rdos.size());
43 const InDetDD::SiDetectorElement * Element = OrigCluster.detectorElement();
44 const InDetDD::PixelModuleDesign& design = dynamic_cast<const InDetDD::PixelModuleDesign&>(Element->design());
45
46 // Check cluster-size bounds.
47 if (NumPixels < m_minPixels || NumPixels > m_maxPixels) return Parts;
48
49 std::vector<InDetDD::SiCellId> CellIds(NumPixels); //NumPixels entries of default constructed SiCellId
50
51 auto getCellId=[Element](const Identifier & i){ return Element->cellIdFromIdentifier(i);};
52 std::transform(Rdos.begin(),Rdos.end(), CellIds.begin(), getCellId);
53
55 const PixelChargeCalibCondData *calibData = *calibDataHandle;
56
57 // Detect special pixels and exclude them if necessary.
58 // Veto removed on 28-7-2011 by K. Barry - residual-level
59 // studies show RMS improvement when ganged-pixel containing
60 // clusters are split.
61
62
63 // Determine maximum and minimum phi and eta indices.
64 auto comparePhi=[](const InDetDD::SiCellId & a, const InDetDD::SiCellId & b){ return (a.phiIndex() < b.phiIndex());};
65 auto compareEta=[](const InDetDD::SiCellId & a, const InDetDD::SiCellId & b){ return (a.etaIndex() < b.etaIndex());};
66 const auto [pMinPhi,pMaxPhi] = std::minmax_element(CellIds.begin(), CellIds.end(), comparePhi);
67 const auto [pMinEta,pMaxEta] = std::minmax_element(CellIds.begin(), CellIds.end(), compareEta);
68 const auto & MinPhiIdx = pMinPhi->phiIndex();
69 const auto & MaxPhiIdx = pMaxPhi->phiIndex();
70 const auto & MinEtaIdx = pMinEta->etaIndex();
71 const auto & MaxEtaIdx = pMaxEta->etaIndex();
72 const int PhiWidth = MaxPhiIdx - MinPhiIdx + 1;
73 const int EtaWidth = MaxEtaIdx - MinEtaIdx + 1;
74
75 // In the future, might want to add a check here to see if the charge list is empty...
76 const std::vector<float> & Charges = OrigCluster.chargeList();
77
78 std::vector<float> PhiChargeHist(PhiWidth, 0.);
79 unsigned int NumPhiMinima = 0;
80 std::vector<unsigned int> PhiMinimaLoc(PhiWidth/2);
81 std::vector<float> PhiMinimaQuality(PhiWidth/2);
82 if (PhiWidth > 2)
83 {
84 // Fill up the phi-charge histogram. The values were initialized to zero by the vector constructor.
85 for (unsigned int i = 0; i < NumPixels; i++)
86 PhiChargeHist[CellIds[i].phiIndex() - MinPhiIdx] += Charges[i];
87
88 // Minima search
89 for (int i = 1; i < PhiWidth - 1; i++)
90 {
91 if (PhiChargeHist[i-1] <= PhiChargeHist[i] || PhiChargeHist[i] >= PhiChargeHist[i+1]) continue;
92
93 PhiMinimaLoc[NumPhiMinima] = static_cast<unsigned int>(i);
94 PhiMinimaQuality[NumPhiMinima++] = (PhiChargeHist[i+1] + PhiChargeHist[i-1] - 2.*PhiChargeHist[i]) /
95 (PhiChargeHist[i+1] + PhiChargeHist[i-1]);
96 }
97 }
98
99 std::vector<float> EtaChargeHist(EtaWidth, 0.);
100 unsigned int NumEtaMinima = 0;
101 std::vector<unsigned int> EtaMinimaLoc(EtaWidth/2);
102 std::vector<float> EtaMinimaQuality(EtaWidth/2);
103 const float LongPixScale = 2./3.;
104 if (EtaWidth > 2)
105 {
106 float Scale;
107 // Fill up the eta-charge histogram. The values were initialized to zero by the vector constructor.
108 for (unsigned int i = 0; i < NumPixels; i++)
109 {
110 const int PixType = pixelType(CellIds[i].phiIndex(), CellIds[i].etaIndex());
111 if ( (PixType % 2) == 1 )
112 Scale = LongPixScale;
113 else
114 Scale = 1.;
115 EtaChargeHist[CellIds[i].etaIndex() - MinEtaIdx] += Scale*Charges[i];
116 }
117
118 // Minima search
119 for (int i = 1; i < EtaWidth - 1; i++)
120 {
121 if (EtaChargeHist[i-1] <= EtaChargeHist[i] || EtaChargeHist[i] >= EtaChargeHist[i+1]) continue;
122
123 EtaMinimaLoc[NumEtaMinima] = static_cast<unsigned int>(i);
124 EtaMinimaQuality[NumEtaMinima++] = (EtaChargeHist[i+1] + EtaChargeHist[i-1] - 2.*EtaChargeHist[i]) /
125 (EtaChargeHist[i+1] + EtaChargeHist[i-1]);
126 }
127 }
128
129 // Select the "best" minimum for splitting
130 unsigned int bestMin = 0;
131 float bestQual = -1.;
133 for (unsigned int i = 0; i < NumPhiMinima; i++)
134 {
135 if (PhiMinimaQuality[i] <= bestQual) continue;
136 Type = PhiSplit;
137 bestMin = PhiMinimaLoc[i];
138 bestQual = PhiMinimaQuality[i];
139 }
140 for (unsigned int i = 0; i < NumEtaMinima; i++)
141 {
142 if (EtaMinimaQuality[i] <= bestQual) continue;
143 Type = EtaSplit;
144 bestMin = EtaMinimaLoc[i];
145 bestQual = EtaMinimaQuality[i];
146 }
147 const int SplitIndex = static_cast<int>(bestMin);
148
149 // Now it's time to do the split!
150 if (Type == NoSplit)
151 {
152 return Parts;
153 }
154 if (Type != PhiSplit && Type != EtaSplit)
155 {
156 // Should never happen...major bug someplace if it does
157 ATH_MSG_ERROR("<InDet::TotPixelClusterSplitter::splitCluster> : Unrecognized SplitType!");
158 return Parts;
159 }
160
161 int Idx;
162 int (InDetDD::SiCellId:: * const IndexFunc) () const = (Type == PhiSplit) ? &InDetDD::SiCellId::phiIndex
164 const int LowIdx = (Type == PhiSplit) ? MinPhiIdx : MinEtaIdx;
165
166 // Variables for PixelClusterParts
167 std::vector<Identifier> SplitRdos[2];
168 std::vector<int> Totgroups[2];
169 std::vector<int> Lvl1groups[2];
170
171 const std::vector<int>& OrigTots = OrigCluster.totList();
172 const int Lvl1a = OrigCluster.LVL1A();
173
174 const AtlasDetectorID* aid = Element->getIdHelper();
175 if (aid==nullptr)
176 {
177 ATH_MSG_ERROR("Could not get ATLASDetectorID");
178 return Parts;
179 }
180
182 ATH_MSG_ERROR("Could not get PixelID pointer");
183 return Parts;
184 }
185 const PixelID* pixelIDp=static_cast<const PixelID*>(aid);
186 const PixelID& pixelID = *pixelIDp;
187 IdentifierHash moduleHash = Element->identifyHash(); // wafer hash
188
189 for (unsigned int i = 0; i < NumPixels; i++)
190 {
191 Idx = (CellIds[i].*IndexFunc)() - LowIdx;
192 if (Idx < SplitIndex)
193 {
194 SplitRdos[0].push_back(Rdos[i]);
195 Totgroups[0].push_back(OrigTots[i]);
196 Lvl1groups[0].push_back(Lvl1a);
197 }
198 else if (Idx > SplitIndex)
199 {
200 SplitRdos[1].push_back(Rdos[i]);
201 Totgroups[1].push_back(OrigTots[i]);
202 Lvl1groups[1].push_back(Lvl1a);
203 }
204 else // only == remains
205 {
206 for (int j = 0; j < 2; j++)
207 {
208
209 Identifier pixid = Rdos[i];
210 assert( Element->identifyHash() == pixelID.wafer_hash(pixelID.wafer_id(pixid)));
211 std::array<InDetDD::PixelDiodeTree::CellIndexType,2> diode_idx
213 pixelID.eta_index(pixid));
215 std::uint32_t feValue = design.getFE(si_param);
216 auto diode_type = design.getDiodeType(si_param);
218 && design.numberOfConnectedCells( design.readoutIdOfCell(InDetDD::SiCellId(diode_idx[0],diode_idx[1])))>1) {
220 }
221
222 SplitRdos[j].push_back(Rdos[i]);
223 Totgroups[j].push_back(calibData->getToT(diode_type, moduleHash, feValue, Charges[i] / 2.0));
224 Lvl1groups[j].push_back(Lvl1a);
225 }
226 }
227 }
228
229 Parts.emplace_back(SplitRdos[0], Totgroups[0], Lvl1groups[0]);
230 Parts.emplace_back(SplitRdos[1], Totgroups[1], Lvl1groups[1]);
231
232 return Parts;
233}
234
235std::vector<InDet::PixelClusterParts> InDet::TotPixelClusterSplitter::splitCluster(
236 const InDet::PixelCluster & OrigCluster,
237 const InDet::PixelClusterSplitProb &) const
238{
239 return splitCluster(OrigCluster);
240}
241
242int InDet::TotPixelClusterSplitter::pixelType(const int PhiIdx, const int EtaIdx)
243{
244 if (EtaIdx%18 != 0 && EtaIdx%18 != 17)
245 {
246 if (PhiIdx==152 || PhiIdx==154 || PhiIdx==156 || PhiIdx==158 ||
247 PhiIdx==169 || PhiIdx==171 || PhiIdx==173 || PhiIdx==175)
248 return 4; // short inter-ganged pixel
249 else if (PhiIdx==153 || PhiIdx==155 || PhiIdx==157 || PhiIdx==159 ||
250 (PhiIdx > 159 && PhiIdx < 168) ||
251 PhiIdx==168 || PhiIdx==170 || PhiIdx==172 || PhiIdx==174)
252 return 2; // short ganged pixel
253 else
254 return 0; // short normal pixel
255 }
256 else
257 {
258 if (PhiIdx==152 || PhiIdx==154 || PhiIdx==156 || PhiIdx==158 ||
259 PhiIdx==169 || PhiIdx==171 || PhiIdx==173 || PhiIdx==175)
260 return 5; // long inter-ganged pixel
261 else if (PhiIdx==153 || PhiIdx==155 || PhiIdx==157 || PhiIdx==159 ||
262 (PhiIdx > 159 && PhiIdx < 168) ||
263 PhiIdx==168 || PhiIdx==170 || PhiIdx==172 || PhiIdx==174)
264 return 3; // long ganged pixel
265 else
266 return 1; // long normal pixel
267 }
268}
269
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
static Double_t a
This class provides an interface to generate or decode an identifier for the upper levels of the dete...
virtual HelperType helper() const
Type of helper, defaulted to 'Unimplemented'.
This is a "hash" representation of an Identifier.
static constexpr std::array< PixelDiodeTree::CellIndexType, 2 > makeCellIndex(T local_x_idx, T local_y_idx)
Create a 2D cell index from the indices in local-x (phi, row) and local-y (eta, column) direction.
Class used to describe the design of a module (diode segmentation and readout scheme)
PixelDiodeTree::DiodeProxyWithPosition diodeProxyFromIdxCachePosition(const std::array< PixelDiodeTree::IndexType, 2 > &idx) const
virtual int numberOfConnectedCells(const SiReadoutCellId &readoutId) const
readout id -> id of connected diodes
PixelReadoutTechnology getReadoutTechnology() const
virtual SiReadoutCellId readoutIdOfCell(const SiCellId &cellId) const
diode id -> readout id
static InDetDD::PixelDiodeType getDiodeType(const PixelDiodeTree::DiodeProxy &diode_proxy)
static unsigned int getFE(const PixelDiodeTree::DiodeProxy &diode_proxy)
Identifier for the strip or pixel cell.
Definition SiCellId.h:29
int phiIndex() const
Get phi index. Equivalent to strip().
Definition SiCellId.h:122
int etaIndex() const
Get eta index.
Definition SiCellId.h:114
Class to hold geometrical description of a silicon detector element.
return object of the IPixelClusterSplitProbTool
virtual const InDetDD::SiDetectorElement * detectorElement() const override final
return the detector element corresponding to this PRD The pointer will be zero if the det el is not d...
unsigned int m_minPixels
Minimum number of pixels in cluster to consider splitting.
SG::ReadCondHandleKey< PixelChargeCalibCondData > m_chargeDataKey
unsigned int m_maxPixels
Maximum size of cluster for which splitting will be attempted.
virtual StatusCode initialize() override
AthAlgTool interface methods.
TotPixelClusterSplitter(const std::string &type, const std::string &name, const IInterface *parent)
Constructor.
static int pixelType(const int PhiIdx, const int EtaIdx)
Determine a pixel's type.
virtual std::vector< InDet::PixelClusterParts > splitCluster(const InDet::PixelCluster &OrigCluster) const override
take one, give zero or many
virtual StatusCode finalize() override
float getToT(InDetDD::PixelDiodeType type, unsigned int moduleHash, unsigned int FE, float Q) const
This is an Identifier helper class for the Pixel subdetector.
Definition PixelID.h:67
int eta_index(const Identifier &id) const
Definition PixelID.h:645
Identifier wafer_id(int barrel_ec, int layer_disk, int phi_module, int eta_module) const
For a single crystal.
Definition PixelID.h:360
IdentifierHash wafer_hash(Identifier wafer_id) const
wafer hash from id
Definition PixelID.h:383
int phi_index(const Identifier &id) const
Definition PixelID.h:639
const std::vector< Identifier > & rdoList() const
return the List of rdo identifiers (pointers)
void Scale(TH1 *h, double d=1)
A diode proxy which caches the position of a diode.