ATLAS Offline Software
PLRGmxInterface.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "PLRGmxInterface.h"
6 
17 
18 
19 namespace InDetDD
20 {
21 
23  SiCommonItems *commonItems,
24  WaferTree *moduleTree)
25  : PixelGmxInterface(detectorManager, commonItems, moduleTree)
26 {}
27 
28 int PLRGmxInterface::sensorId(std::map<std::string, int> &index) const
29 {
30  // Return the Simulation HitID (nothing to do with "ATLAS Identifiers" aka "Offline Identifiers")
31 
32  // Check if identifier is valid
33  // TODO: drop this check in the future
34  const PLR_ID *pixelIdHelper = dynamic_cast<const PLR_ID *>(m_commonItems->getIdHelper());
35  if (not pixelIdHelper){
36  ATH_MSG_ERROR("Failed dynamic_cast to PLR_ID in PLRGmxInterface::sensorId");
37  return -1;
38  }
39  Identifier id = pixelIdHelper->wafer_id(index["barrel_endcap"],
40  index["layer_wheel"],
41  index["phi_module"],
42  index["eta_module"]);
43  IdentifierHash hashId = pixelIdHelper->wafer_hash(id);
44  if (!hashId.is_valid()) {
45  ATH_MSG_WARNING("PLR Invalid hash for Index list: " << index["barrel_endcap"] << " " << index["layer_wheel"] << " "
46  << index["eta_module"] << " " << index["phi_module"] << " " << index["side"]);
47  return -1;
48  }
49  // Compute the actuall SiHitId, first number is the part number: lumi=2
50  int hitIdOfModule = SiHitIdHelper::GetHelper()->buildHitId(2,
51  index["barrel_endcap"],
52  index["layer_wheel"],
53  index["eta_module"],
54  index["phi_module"],
55  index["side"]);
56  ATH_MSG_DEBUG("Index list: " << index["barrel_endcap"] << " " << index["layer_wheel"] << " "
57  << index["eta_module"] << " " << index["phi_module"] << " " << index["side"]);
58  ATH_MSG_DEBUG("hitIdOfModule = " << std::hex << hitIdOfModule << std::dec);
59  ATH_MSG_DEBUG(" bec = " << SiHitIdHelper::GetHelper()->getBarrelEndcap(hitIdOfModule)
60  << " lay = " << SiHitIdHelper::GetHelper()->getLayerDisk(hitIdOfModule)
61  << " eta = " << SiHitIdHelper::GetHelper()->getEtaModule(hitIdOfModule)
62  << " phi = " << SiHitIdHelper::GetHelper()->getPhiModule(hitIdOfModule)
63  << " side = " << SiHitIdHelper::GetHelper()->getSide(hitIdOfModule));
64 
65  return hitIdOfModule;
66 }
67 
68 
69 void PLRGmxInterface::addSensorType(const std::string& clas,
70  const std::string& typeName,
71  const std::map<std::string, std::string>& parameters)
72 {
73  ATH_MSG_DEBUG("addSensorType called for class " << clas << ", typeName " << typeName);
74  // only load the sensor type that the PLR will use
75  if (clas == "SingleChip_RD53" && (typeName == "RD53_20x19_Single_25x100" || typeName == "PLR_20x19_Single_25x100")) {
77  }
78 }
79 
80 
81 void PLRGmxInterface::addSensor(const std::string& typeName,
82  std::map<std::string, int> &index,
83  int /*sensitiveId*/,
84  GeoVFullPhysVol *fpv)
85 {
86  //
87  // Get the ATLAS "Offline" wafer identifier
88  //
89  const PLR_ID *pixelIdHelper = dynamic_cast<const PLR_ID *>(m_commonItems->getIdHelper());
90  if (not pixelIdHelper){
91  ATH_MSG_ERROR("Failed dynamic_cast to PLR_ID in PLRGmxInterface::addSensor");
92  return;
93  }
94  Identifier id = pixelIdHelper->wafer_id(index["barrel_endcap"],
95  index["layer_wheel"],
96  index["phi_module"],
97  index["eta_module"]);
98  IdentifierHash hashId = pixelIdHelper->wafer_hash(id);
99  //
100  // Now do our best to check if this is a valid id. If either the gmx file is wrong, or the xml file
101  // defining the allowed id's is wrong, you can get disallowed id's. These cause a crash later
102  // if allowed through. To do the check, we ask for the hash-id of this id. Invalid ids give a
103  // special invalid hash-id (0xFFFFFFFF). But we don't exit the run, to help debug things quicker.
104  //
105  if (!hashId.is_valid()) {
106  ATH_MSG_ERROR("Invalid id for sensitive module " << typeName << " volume with indices");
107  for (const auto& [key, value] : index) {
108  msg() << MSG::ERROR << key << " = " << value << "; ";
109  }
110  msg() << MSG::ERROR << endmsg;
111  ATH_MSG_ERROR("Refusing to make it into a sensitive element. Incompatible gmx and identifier-xml files.");
112  return;
113  }
114 
115  //
116  // Create the detector element and add to the DetectorManager
117  //
118  auto it = m_geometryMap.find(typeName);
119  if(it == m_geometryMap.end()) {
120  ATH_MSG_ERROR("addSensor: Error: Readout sensor type " << typeName << " not found.");
121  throw std::runtime_error("readout sensor type " + typeName + " not found.");
122  }
123  const SiDetectorDesign *design = m_detectorManager->getDesign(it->second);
124  ATH_MSG_VERBOSE("Adding sensor with design: " << typeName << " " << design);
125  if (design == nullptr) {
126  ATH_MSG_ERROR("addSensor: Error: Readout sensor type " << typeName << " not found.");
127  throw std::runtime_error("readout sensor type " + typeName + " not found.");
128  }
129 
131 
132  //
133  // Build up a map-structure for numerology
134  //
135  Wafer module((unsigned int) hashId);
136  std::string errorMessage("");
137  if (!m_moduleTree->add(index["barrel_endcap"],
138  index["layer_wheel"],
139  index["eta_module"],
140  index["phi_module"],
141  module,
142  errorMessage)) {
143  ATH_MSG_ERROR(errorMessage);
144  }
145 
146  return;
147 }
148 
149 
150 void PLRGmxInterface::makePLRModule(const std::string &typeName,
151  const std::map<std::string, std::string> &parameters)
152 {
153  int circuitsPerEta{1}; // row
154  int circuitsPerPhi{1}; // column
155  double thickness{0.150};
156  double pitchEta{};
157  double pitchPhi{};
158  double pitchEtaLong{};
159  double pitchPhiLong{};
160  double pitchEtaEnd{};
161  double pitchPhiEnd{};
162  int nEtaLongPerSide{};
163  int nPhiLongPerSide{};
164  int nEtaEndPerSide{};
165  int nPhiEndPerSide{};
166  int rowsPerCircuit{};
167  int columnsPerCircuit{};
168 
169  // unused
171  int readoutSide{1};
172  bool is3D{true};
173 
174  // read parameters
175  getParameter(typeName, parameters, "circuitsPerEta", circuitsPerEta);
176  getParameter(typeName, parameters, "circuitsPerPhi", circuitsPerPhi);
177  getParameter(typeName, parameters, "thickness", thickness);
178  getParameter(typeName, parameters, "is3D", is3D);
179  getParameter(typeName, parameters, "rows", rowsPerCircuit);
180  getParameter(typeName, parameters, "columns", columnsPerCircuit);
181  getParameter(typeName, parameters, "pitchEta", pitchEta);
182  getParameter(typeName, parameters, "pitchPhi", pitchPhi);
183  getParameter(typeName, parameters, "pitchEtaLong", pitchEtaLong);
184  getParameter(typeName, parameters, "pitchPhiLong", pitchPhiLong);
185  getParameter(typeName, parameters, "pitchEtaEnd", pitchEtaEnd);
186  getParameter(typeName, parameters, "pitchPhiEnd", pitchPhiEnd);
187  getParameter(typeName, parameters, "nPhiLongPerSide", nPhiLongPerSide);
188  getParameter(typeName, parameters, "nEtaLongPerSide", nEtaLongPerSide);
189  getParameter(typeName, parameters, "nPhiEndPerSide", nPhiEndPerSide);
190  getParameter(typeName, parameters, "nEtaEndPerSide", nEtaEndPerSide);
191 
193 
194  // helper function to associate attributes to sub-matrices and diodes.
195  auto computeAttribute = [pitchPhi,
196  pitchEta,
197  rowsPerCircuit,
198  columnsPerCircuit
199  ](const std::array<PixelDiodeTree::IndexType,2> &split_idx,
200  const PixelDiodeTree::Vector2D &diode_width,
201  [[maybe_unused]] const std::array<bool,4> &ganged,
202  [[maybe_unused]] unsigned int split_i,
203  PixelDiodeTree::AttributeType current_matrix_attribute,
204  PixelDiodeTree::AttributeType current_diode_attribute)
205  -> std::tuple<PixelDiodeTree::AttributeType,PixelDiodeTree::AttributeType>
206  {
207  assert (readoutTechnology==InDetDD::PixelReadoutTechnology::RD53);
208  // split_idx the absolute index at which this sub-matrix is split into 4 sub-sub-matrices
209  // diode_width the diode pitch in both directions
210  // ganged ganged[0],ganged[1] whether the pixel diode is ganged in the corresponding direction
211  // ganged[2],ganged[3] whether the diode is inside (true) or outside the dead zone
212  // where ganged[2] denotes the flag in local-x and ganged[3] in local-y direction
213  //
214  // split_i defines which of the 4 areas the diode belongs to : 2 | 3 ^
215  // ----- | local-y (chip-columns)
216  // 0 | 1 |
217  // ---> local-x (chip-rows)
218  //
219  // current_matrix_attribute the default attribute for the unsplit sub-matrix assigned by the builder
220  // current_diode_attribute the default attribute assigned to the current diode associated to the split
221  // area specified by split_i
222  // return new matrix attribute, new diode attribute
223 
224  // if the pixel is significantly wider in one direction consider the pixel to be long
225  // or if wider in both directions large
226  assert(split_idx[0]>=0 && split_idx[1]>=0);
227  std::array<int,2> chip_idx{split_idx[0]/rowsPerCircuit, split_idx[1]/columnsPerCircuit};
228 
229  unsigned int n_large_dimensions = ( (std::abs(diode_width[0]-pitchPhi)>pitchPhi*.25)
230  +(std::abs(diode_width[1]-pitchEta)>pitchEta*.25));
231  switch (n_large_dimensions) {
232  case 1:
234  break;
235  case 2:
237  break;
238  default:
240  }
241 
242  current_matrix_attribute = InDetDD::detail::makeAttributeType(chip_idx[1] + chip_idx[0]*2);
243  return std::make_tuple(current_matrix_attribute, current_diode_attribute);
244  };
245 
246  PixelDiodeTree diode_tree
247  = createPixelDiodeTree(std::array<unsigned int,2>{static_cast<unsigned int>(circuitsPerPhi),static_cast<unsigned int>(circuitsPerEta)},
248  std::array<unsigned int,2>{static_cast<unsigned int>(rowsPerCircuit),static_cast<unsigned int>(columnsPerCircuit)},
249  PixelDiodeTree::Vector2D{pitchPhi,pitchEta}, // regular ptich
250  std::array<std::array<unsigned int,2>, 2>{ std::array<unsigned int,2>{static_cast<unsigned int>(nPhiEndPerSide),
251  static_cast<unsigned int>(nEtaEndPerSide)}, // outer edge in pixels
252  std::array<unsigned int,2>{static_cast<unsigned int>(nPhiLongPerSide),
253  static_cast<unsigned int>(nEtaLongPerSide)}}, // inner edge in pixels
254  std::array<PixelDiodeTree::Vector2D,2>{PixelDiodeTree::Vector2D{pitchPhiEnd, pitchEtaEnd}, // outer edge pitch (correct?)
255  PixelDiodeTree::Vector2D{pitchPhiLong,pitchEtaLong} // inner edge pitch
256  },
257  std::array<std::array<unsigned int,2>, 2>{ std::array<unsigned int,2>{0u,0u}, // @TODO add dead zone for run1-3 pixels
258  std::array<unsigned int,2>{0u,0u} // @TODO add dead zone for run1-3 pixels
259  },
260  computeAttribute,
261  nullptr);
262 
263  // Setting module identifier to InDetDD::PLR
264  // (so far) primarily useful to avoid orientation warnings
265  InDetDD::DetectorType detectorType{InDetDD::PLR};
266 
267  auto design = std::make_unique<PixelModuleDesign>(thickness,
268  circuitsPerPhi, circuitsPerEta,
269  columnsPerCircuit, rowsPerCircuit,
270  columnsPerCircuit, rowsPerCircuit,
271  std::move(diode_tree), carrier,
272  readoutSide, is3D, detectorType,
273  readoutTechnology);
274 
275  ATH_MSG_DEBUG("readout geo - design " << typeName << " " << design->width() << "x" << design->length() << "x" << design->thickness()
276  << " " << design->rows() << "x" << design->columns()
277  << ", " << circuitsPerPhi << "x" << circuitsPerEta << " "
278  << rowsPerCircuit << "x" << columnsPerCircuit
279  << " carrier " << carrier << " readout side " << readoutSide << ":\n"
280  << diode_tree.debugStringRepr());
281 
282  [[maybe_unused]] auto observedPtr = m_detectorManager->addDesign(std::move(design));
283 
284  // Add to map for addModule routine
286 }
287 
288 } // namespace InDetDD
InDetDD::PixelDiodeTree
Tree structure to find the position, index or pitch of a pixel on a semi-regular grid The grid is con...
Definition: PixelDiodeTree.h:33
InDetDD::PixelReadoutTechnology
PixelReadoutTechnology
Definition: PixelReadoutDefinitions.h:37
InDetDD::PLR
@ PLR
Definition: DetectorDesign.h:46
InDetDD::SiCommonItems::getIdHelper
const AtlasDetectorID * getIdHelper() const
Definition: SiCommonItems.h:83
index
Definition: index.py:1
InDetDD::SiDetectorManager::numDesigns
int numDesigns() const
Definition: SiDetectorManager.cxx:140
PLR_ID.h
skel.it
it
Definition: skel.GENtoEVGEN.py:407
PLR_ID
This is a Identifier helper class for the PLR subdetector. This class inherits from PixelID.
Definition: PLR_ID.h:22
InDetDD::SiDetectorManager::addDesign
const SiDetectorDesign * addDesign(std::unique_ptr< const SiDetectorDesign > &&)
Access to module design; returns an observer pointer.
Definition: SiDetectorManager.cxx:134
athena.value
value
Definition: athena.py:124
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
InDetDD::ITk::PixelGmxInterface::m_moduleTree
WaferTree * m_moduleTree
Definition: PixelGmxInterface.h:60
Trk::u
@ u
Enums for curvilinear frames.
Definition: ParamDefs.h:77
InDetDD::ITk::PixelGmxInterface::m_geometryMap
std::map< std::string, int > m_geometryMap
Definition: PixelGmxInterface.h:53
InDetDD::PixelReadoutTechnology::RD53
@ RD53
PixelConditionsData::getParameter
std::vector< T > getParameter(const std::string &varName, const std::vector< std::string > &buffer)
Definition: PixelConditionsDataStringUtils.h:51
InDetDD::PLRGmxInterface::addSensorType
virtual void addSensorType(const std::string &clas, const std::string &typeName, const std::map< std::string, std::string > &parameters) override final
Definition: PLRGmxInterface.cxx:69
SiHitIdHelper.h
python.PyAthena.module
module
Definition: PyAthena.py:131
InDetDD::PLRGmxInterface::addSensor
virtual void addSensor(const std::string &typeName, std::map< std::string, int > &index, int sequentialId, GeoVFullPhysVol *fpv) override final
Definition: PLRGmxInterface.cxx:81
PixelDetectorManager.h
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
InDetDD::PixelDiodeType::LONG
@ LONG
InDetDD::DetectorType
DetectorType
Definition: DetectorDesign.h:45
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
SiCommonItems.h
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Wafer
Definition: WaferTree.h:27
BarrelEndcap::add
bool add(int bec, int ld, int eta, int phi, int side, Wafer &wafer, std::string &errorMessage)
Definition: WaferTree.cxx:55
InDetDD::PixelDiodeTree::AttributeType
unsigned int AttributeType
Definition: PixelDiodeTree.h:39
InDetDD::SiDetectorManager::getDesign
const SiDetectorDesign * getDesign(int i) const
Definition: SiDetectorManager.cxx:146
InDetDD::PLRGmxInterface::makePLRModule
void makePLRModule(const std::string &typeName, const std::map< std::string, std::string > &parameters)
Definition: PLRGmxInterface.cxx:150
InDetDD::PixelDiodeType::LARGE
@ LARGE
InDetDD::ITk::PixelGmxInterface::m_commonItems
SiCommonItems * m_commonItems
Definition: PixelGmxInterface.h:59
AthMessaging::msg
MsgStream & msg() const
The standard message stream.
Definition: AthMessaging.h:164
IdentifierHash::is_valid
bool is_valid() const
Check if id is in a valid state.
WaferTree.h
InDetDD::PixelDetectorManager
Definition: PixelDetectorManager.h:47
InDetDD::SiCommonItems
Definition: SiCommonItems.h:45
InDetDD::PixelDiodeTree::debugStringRepr
std::string debugStringRepr() const
Dump the diode tree structure into a string.
Definition: PixelDiodeTree.cxx:97
InDetDD::SiDetectorElement
Definition: SiDetectorElement.h:109
InDetDD::detail::makeAttributeType
InDetDD::PixelDiodeTree::AttributeType makeAttributeType(T val)
convenience method to convert the given value into an attribute
Definition: PixelDiodeTreeBuilder.h:79
InDetDD::PixelDiodeTree::Vector2D
Amg::Vector2D Vector2D
Definition: PixelDiodeTree.h:35
SiDetectorElement.h
PLRGmxInterface.h
InDetDD::ITk::PixelGmxInterface::m_detectorManager
PixelDetectorManager * m_detectorManager
Definition: PixelGmxInterface.h:58
InDetDD::CarrierType
CarrierType
Definition: InDetDD_Defs.h:17
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
InDetDD
Message Stream Member.
Definition: FakeTrackBuilder.h:8
PixelModuleDesign.h
SiHitIdHelper::GetHelper
static const SiHitIdHelper * GetHelper()
Definition: SiHitIdHelper.cxx:19
physics_parameters.parameters
parameters
Definition: physics_parameters.py:144
ReadCalibFromCool.typeName
typeName
Definition: ReadCalibFromCool.py:477
InDetDD::PixelDiodeType::NORMAL
@ NORMAL
PixelDiodeTreeBuilder.h
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::SiDetectorDesign
Definition: SiDetectorDesign.h:50
InDetDD::PLRGmxInterface::sensorId
virtual int sensorId(std::map< std::string, int > &index) const override final
Definition: PLRGmxInterface.cxx:28
SiHitIdHelper::buildHitId
int buildHitId(const int, const int, const int, const int, const int, const int) const
Definition: SiHitIdHelper.cxx:118
InDetDD::createPixelDiodeTree
PixelDiodeTree createPixelDiodeTree(const std::array< unsigned int, 2 > &chip_dim, const std::array< unsigned int, 2 > &chip_matrix_dim, const PixelDiodeTree::Vector2D &pitch, const std::array< std::array< unsigned int, 2 >, 2 > &edge_dim, const std::array< PixelDiodeTree::Vector2D, 2 > &edge_pitch, const std::array< std::array< unsigned int, 2 >, 2 > &dead_zone, const AttributeRefiner &func_compute_attribute, std::ostream *debug_out=nullptr)
Create a pixel diode tree.
Definition: PixelDiodeTreeBuilder.cxx:224
PixelDiodeTree.h
InDetDD::PLRGmxInterface::PLRGmxInterface
PLRGmxInterface(PixelDetectorManager *detectorManager, SiCommonItems *commonItems, WaferTree *moduleTree)
Definition: PLRGmxInterface.cxx:22
SiDetectorDesign.h
InDetDD::electrons
@ electrons
Definition: InDetDD_Defs.h:17
InDetDD::PixelDetectorManager::addDetectorElement
virtual void addDetectorElement(SiDetectorElement *element) override
Add elememts.
Definition: PixelDetectorManager.cxx:128
WaferTree
Definition: WaferTree.h:74
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
Identifier
Definition: IdentifierFieldParser.cxx:14