ATLAS Offline Software
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 
18 InDet::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 
28 
29  return StatusCode::SUCCESS;
30 }
31 
33  return StatusCode::SUCCESS;
34 }
35 
36 std::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) {
219  diode_type = InDetDD::PixelDiodeType::GANGED;
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 
235 std::vector<InDet::PixelClusterParts> InDet::TotPixelClusterSplitter::splitCluster(
236  const InDet::PixelCluster & OrigCluster,
237  const InDet::PixelClusterSplitProb &) const
238 {
239  return splitCluster(OrigCluster);
240 }
241 
242 int 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 
PixelChargeCalibCondData::getToT
float getToT(InDetDD::PixelDiodeType type, unsigned int moduleHash, unsigned int FE, float Q) const
Definition: PixelChargeCalibCondData.cxx:174
PixelID::phi_index
int phi_index(const Identifier &id) const
Definition: PixelID.h:639
InDet::TotPixelClusterSplitter::EtaSplit
@ EtaSplit
Definition: TotPixelClusterSplitter.h:78
SG::ReadCondHandle
Definition: ReadCondHandle.h:40
InDetDD::PixelModuleDesign
Definition: PixelModuleDesign.h:45
AtlasDetectorID::HelperType::Pixel
@ Pixel
InDet::PixelClusterSplitProb
Definition: PixelClusterSplitProb.h:25
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
PixelCluster.h
Trk::PrepRawData::rdoList
const std::vector< Identifier > & rdoList() const
return the List of rdo identifiers (pointers)
InDet::TotPixelClusterSplitter::NoSplit
@ NoSplit
Definition: TotPixelClusterSplitter.h:78
InDet::TotPixelClusterSplitter::pixelType
static int pixelType(const int PhiIdx, const int EtaIdx)
Determine a pixel's type.
Definition: TotPixelClusterSplitter.cxx:242
InDetDD::PixelReadoutTechnology::FEI3
@ FEI3
InDet::TotPixelClusterSplitter::finalize
virtual StatusCode finalize() override
Definition: TotPixelClusterSplitter.cxx:32
TotPixelClusterSplitter.h
InDet::TotPixelClusterSplitter::initialize
virtual StatusCode initialize() override
AthAlgTool interface methods.
Definition: TotPixelClusterSplitter.cxx:25
InDetDD::SiCellId::phiIndex
int phiIndex() const
Get phi index. Equivalent to strip().
Definition: SiCellId.h:122
InDet::TotPixelClusterSplitter::m_chargeDataKey
SG::ReadCondHandleKey< PixelChargeCalibCondData > m_chargeDataKey
Definition: TotPixelClusterSplitter.h:81
InDetDD::PixelModuleDesign::getFE
static unsigned int getFE(const PixelDiodeTree::DiodeProxy &diode_proxy)
Definition: PixelModuleDesign.h:258
InDetDD::PixelModuleDesign::diodeProxyFromIdxCachePosition
PixelDiodeTree::DiodeProxyWithPosition diodeProxyFromIdxCachePosition(const std::array< PixelDiodeTree::IndexType, 2 > &idx) const
Definition: PixelModuleDesign.h:251
InDet::PixelCluster::totList
const std::vector< int > & totList() const
Definition: InnerDetector/InDetRecEvent/InDetPrepRawData/InDetPrepRawData/PixelCluster.h:202
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
InDetDD::PixelDiodeType::GANGED
@ GANGED
InDetDD::SolidStateDetectorElementBase::identifyHash
virtual IdentifierHash identifyHash() const override final
identifier hash (inline)
PixelID::wafer_id
Identifier wafer_id(int barrel_ec, int layer_disk, int phi_module, int eta_module) const
For a single crystal.
Definition: PixelID.h:360
InDet::TotPixelClusterSplitter::splitCluster
virtual std::vector< InDet::PixelClusterParts > splitCluster(const InDet::PixelCluster &OrigCluster) const override
take one, give zero or many
Definition: TotPixelClusterSplitter.cxx:37
InDetDD::SolidStateDetectorElementBase::getIdHelper
const AtlasDetectorID * getIdHelper() const
Returns the id helper (inline)
Muon::PhiIdx
MuonStationIndex::PhiIndex PhiIdx
Definition: MuonTruthHitPlots.cxx:10
InDetDD::PixelModuleDesign::getDiodeType
static InDetDD::PixelDiodeType getDiodeType(const PixelDiodeTree::DiodeProxy &diode_proxy)
Definition: PixelModuleDesign.h:261
GeoPrimitives.h
InDetDD::PixelDiodeTree::DiodeProxyWithPosition
A diode proxy which caches the position of a diode.
Definition: PixelDiodeTree.h:230
InDetDD::SiDetectorElement::cellIdFromIdentifier
virtual SiCellId cellIdFromIdentifier(const Identifier &identifier) const override final
SiCellId from Identifier.
Definition: SiDetectorElement.cxx:120
InDetDD::SiCellId::etaIndex
int etaIndex() const
Get eta index.
Definition: SiCellId.h:114
PixelID::wafer_hash
IdentifierHash wafer_hash(Identifier wafer_id) const
wafer hash from id
Definition: PixelID.h:383
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:85
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
PixelChargeCalibCondData
Definition: PixelChargeCalibCondData.h:24
Amg::transform
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Definition: GeoPrimitivesHelpers.h:156
test_pyathena.parent
parent
Definition: test_pyathena.py:15
PixelID::eta_index
int eta_index(const Identifier &id) const
Definition: PixelID.h:645
InDet::PixelCluster::LVL1A
int LVL1A() const
Definition: InnerDetector/InDetRecEvent/InDetPrepRawData/InDetPrepRawData/PixelCluster.h:270
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Scale
void Scale(TH1 *h, double d=1)
Definition: comparitor.cxx:79
xAODType
Definition: ObjectType.h:13
InDet::SiCluster::detectorElement
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...
AtlasDetectorID::helper
virtual HelperType helper() const
Type of helper, defaulted to 'Unimplemented'.
Definition: AtlasDetectorID.h:90
EventPrimitives.h
InDetDD::PixelModuleDesign::numberOfConnectedCells
virtual int numberOfConnectedCells(const SiReadoutCellId &readoutId) const
readout id -> id of connected diodes
Definition: PixelModuleDesign.cxx:224
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
InDet::TotPixelClusterSplitter::TotPixelClusterSplitter
TotPixelClusterSplitter(const std::string &type, const std::string &name, const IInterface *parent)
Constructor.
Definition: TotPixelClusterSplitter.cxx:18
InDetDD::SiDetectorElement
Definition: SiDetectorElement.h:109
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
InDetDD::PixelModuleDesign::getReadoutTechnology
PixelReadoutTechnology getReadoutTechnology() const
Definition: PixelModuleDesign.h:391
SiDetectorElement.h
InDetDD::SiCellId
Definition: SiCellId.h:29
eflowRec::phiIndex
unsigned int phiIndex(float phi, float binsize)
calculate phi index for a given phi
Definition: EtaPhiLUT.cxx:23
InDet::PixelCluster
Definition: InnerDetector/InDetRecEvent/InDetPrepRawData/InDetPrepRawData/PixelCluster.h:49
InDet::TotPixelClusterSplitter::m_maxPixels
unsigned int m_maxPixels
Maximum size of cluster for which splitting will be attempted.
Definition: TotPixelClusterSplitter.h:87
a
TList * a
Definition: liststreamerinfos.cxx:10
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
PixelModuleDesign.h
InDet::TotPixelClusterSplitter::PhiSplit
@ PhiSplit
Definition: TotPixelClusterSplitter.h:78
InDetDD::PixelModuleDesign::readoutIdOfCell
virtual SiReadoutCellId readoutIdOfCell(const SiCellId &cellId) const
diode id -> readout id
Definition: PixelModuleDesign.cxx:242
InDetDD::PixelDiodeTree::makeCellIndex
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.
Definition: PixelDiodeTree.h:320
IdentifierHash
This is a "hash" representation of an Identifier. This encodes a 32 bit index which can be used to lo...
Definition: IdentifierHash.h:25
InDetDD::SiDetectorElement::design
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
PixelID
Definition: PixelID.h:67
AtlasDetectorID
This class provides an interface to generate or decode an identifier for the upper levels of the dete...
Definition: AtlasDetectorID.h:52
InDet::TotPixelClusterSplitter::SplitType
SplitType
Definition: TotPixelClusterSplitter.h:78
InDet::PixelCluster::chargeList
const std::vector< float > & chargeList() const
Definition: InnerDetector/InDetRecEvent/InDetPrepRawData/InDetPrepRawData/PixelCluster.h:210
Identifier
Definition: IdentifierFieldParser.cxx:14