Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LayerFactory.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file LayerFactory.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2022 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
13 
14 #include <DD4hep/DetFactoryHelper.h>
15 #include <DD4hep/Objects.h>
16 #include <DDRec/DetectorData.h>
17 #include <XML/Utilities.h>
18 
19 #include "DD4hepTestsHelper.hpp"
20 
21 using namespace std;
22 using namespace dd4hep;
23 
31 DetElement addCylinderLayer(Detector &dd, Assembly &dAssembly,
32  const xml_comp_t &x_layer, SensitiveDetector sens,
33  int layerID = 0) {
34  // Make the cylinder detector element
35  auto layerName = x_layer.nameStr();
36  DetElement layerElement(layerName, layerID);
37  // Layer parameters
38  auto &layerParams =
39  DD4hepTestsHelper::ensureExtension<dd4hep::rec::VariantParameters>(
40  layerElement);
41 
42  // The layer Assembly
43  Assembly layerAssembly(layerName + std::to_string(layerID));
44  layerAssembly.setVisAttributes(dd, x_layer.visStr());
45  // Check if a volume definition is present
46  if (x_layer.hasChild(_Unicode(acts_volume))) {
47  xml_comp_t acts_volume = x_layer.child(_Unicode(acts_volume));
48  layerParams.set<bool>("acts_volume", true);
49  if (acts_volume.hasChild(_U(tubs))) {
50  xml_comp_t acts_tubs = acts_volume.child(_Unicode(tubs));
51  layerParams.set<int>("acts_volume_type",
52  int(Acts::VolumeBounds::BoundsType::eCylinder));
53  layerParams.set<int>("acts_volume_bvalues_n", 3);
54  layerParams.set<double>("acts_volume_bvalues_0", acts_tubs.rmin());
55  layerParams.set<double>("acts_volume_bvalues_1", acts_tubs.rmax());
56  layerParams.set<double>("acts_volume_bvalues_2", 0.5 * acts_tubs.dz());
57  // Decode a position (shift)
58  std::vector<std::string> posKeys = {"x", "y", "z"};
59  for (const auto &pk : posKeys) {
60  layerParams.set<double>(
61  "acts_volume_pos_" + pk,
62  Acts::getAttrValueOr<double>(acts_tubs, pk, 0.));
63  }
64  }
65  }
66 
67  // Active layer surfaces - Count and fill the sensors
68  if (x_layer.hasChild(_Unicode(modules))) {
69  // Check if the cylinder has a surface binning instruction
70  if (x_layer.hasChild(_Unicode(acts_surface_binning))) {
71  xml_comp_t sfBinning = x_layer.child(_Unicode(acts_surface_binning));
72  Acts::decodeBinning(layerParams, sfBinning, "acts_surface_binning",
73  {"z", "phi"});
74  }
75  // Go through the sensors
76  unsigned int sensorID = 1u;
77  xml_comp_t x_det_modules = x_layer.child(_Unicode(modules));
78  for (xml_coll_t bmodule(x_det_modules, _U(box)); bmodule != nullptr;
79  ++bmodule) {
80  xml_comp_t x_det_box = bmodule;
81 
82  // Due to convention this causes an axis flip on x
83  Box boxShape(0.5 * x_det_box.dx(), 0.5 * x_det_box.dy(),
84  0.5 * x_det_box.dz());
85 
86  // Set an orientation
87  DetElement boxElement(layerName + "_module" + std::to_string(sensorID),
88  sensorID);
89 
90  Volume boxVolume(layerName, boxShape,
91  dd.material(x_det_box.materialStr()));
92  boxVolume.setVisAttributes(dd, x_det_box.visStr());
93  boxVolume.setSensitiveDetector(sens);
94 
95  PlacedVolume placedBox = layerAssembly.placeVolume(
96  boxVolume, DD4hepTestsHelper::createTransform(x_det_box));
97 
98  placedBox.addPhysVolID("sensor", sensorID++);
99  boxElement.setPlacement(placedBox);
100  // Add the module elements
101  layerElement.add(boxElement);
102  }
103  }
104  // Passive layer surface - place it inside the envelope
105  for (xml_coll_t psurface(x_layer, _Unicode(acts_passive_surface));
106  psurface != nullptr; ++psurface) {
107  xml_comp_t x_passive_xml = psurface;
108  // Direct definition of a child surface
109  if (x_passive_xml.hasChild(_Unicode(tubs))) {
110  xml_comp_t x_tubs_t = x_passive_xml.child(_Unicode(tubs));
111  // Crete the corresponding detector element
112  DetElement passiveElement(layerName + "_passiveEl", x_layer.id());
113  Tube passiveShape(layerName + "_shape", x_tubs_t.rmin(), x_tubs_t.rmax(),
114  x_tubs_t.dz());
115  Volume passiveVolume(layerName + "_volume", passiveShape,
116  dd.material(x_tubs_t.materialStr()));
117  passiveVolume.setVisAttributes(dd, x_layer.visStr());
118  // The places layer after all
119  PlacedVolume placedPassive = layerAssembly.placeVolume(
120  passiveVolume, DD4hepTestsHelper::createTransform(x_passive_xml));
121  // Transport the passive surface knowledge
122  auto &params =
123  DD4hepTestsHelper::ensureExtension<dd4hep::rec::VariantParameters>(
124  passiveElement);
125  params.set<bool>("acts_passive_surface", true);
126  // Set the placement and add
127  passiveElement.setPlacement(placedPassive);
128  // Add the module elements
129  layerElement.add(passiveElement);
130  }
131  }
132 
133  auto placedLayer = dAssembly.placeVolume(layerAssembly);
134  placedLayer.addPhysVolID("layer", layerID);
135  layerElement.setPlacement(placedLayer);
136  // Return the layer element
137  return layerElement;
138 }
139 
148 static Ref_t create_barrel_detector(Detector &dd, xml_h xml,
149  SensitiveDetector sens) {
150  xml_det_t x_det = xml;
151  string detName = x_det.nameStr();
152 
153  // create the master detector element
154  DetElement detectorElement(detName, x_det.id());
155  dd4hep::xml::setDetectorTypeFlag(xml, detectorElement);
156 
157  // The Shape and Volume
158  Assembly detectorAssembly(detName);
159  detectorAssembly.setVisAttributes(dd, x_det.visStr());
160 
161  // Add layers if they exist as such
162  if (x_det.hasChild(_Unicode(layers))) {
163  xml_comp_t x_det_layers = x_det.child(_Unicode(layers));
164  int layerID = 0;
165  for (xml_coll_t layer(x_det_layers, _Unicode(layer)); layer != nullptr;
166  ++layer) {
167  xml_comp_t x_det_layer = layer;
168  auto layerElement =
169  addCylinderLayer(dd, detectorAssembly, x_det_layer, sens, layerID++);
170  // Add is to the detector element
171  detectorElement.add(layerElement);
172  }
173  }
174  // Place it into the mother volume
175  Volume motherVolume = dd.pickMotherVolume(detectorElement);
176  Position translation(0., 0., 0.);
177  PlacedVolume placedDetector =
178  motherVolume.placeVolume(detectorAssembly, translation);
179  // "system" is hard coded in the DD4Hep::VolumeManager
180  placedDetector.addPhysVolID("system", x_det.id());
181  detectorElement.setPlacement(placedDetector);
182 
183  // return this element
184  return detectorElement;
185 }
186 
187 DECLARE_DETELEMENT(BarrelDetector, create_barrel_detector)
188 
189 
190 
191 
192 
193 
194 
195 
196 static Ref_t create_disc_layer(Detector &dd, xml_h xml,
197  SensitiveDetector sens) {
198  xml_det_t x_det = xml;
199  string detName = x_det.nameStr();
200 
201  xml_comp_t x_det_env = x_det.child(_Unicode(envelope));
202 
203  // Make DetElement
204  DetElement discLayerElement(detName, x_det.id());
205  dd4hep::xml::setDetectorTypeFlag(xml, discLayerElement);
206 
207  auto &layerParams =
208  DD4hepTestsHelper::ensureExtension<dd4hep::rec::VariantParameters>(
209  discLayerElement);
210 
211  // Check if the disk has a surface binning instruction
212  if (x_det.hasChild(_Unicode(acts_surface_binning))) {
213  xml_comp_t sfBinning = x_det.child(_Unicode(acts_surface_binning));
214  Acts::decodeBinning(layerParams, sfBinning, "acts_surface_binning",
215  {"r", "phi"});
216  }
217 
218  // Create the envelope
219  DetElement envelopeElement(detName + "_envelope", x_det.id());
220  Tube envelopeShape(detName + "_shape", x_det_env.rmin(), x_det_env.rmax(),
221  x_det_env.dz());
222  Volume envelopeVolume(detName, envelopeShape,
223  dd.material(x_det_env.materialStr()));
224  envelopeVolume.setVisAttributes(dd, x_det.visStr());
225 
226  // Active layer ...
227  //
228  // Count and fill the sensors
229  if (x_det.hasChild(_Unicode(modules))) {
230  unsigned int sensorID = 1u;
231  xml_comp_t x_det_modules = x_det.child(_Unicode(modules));
232 
233  for (xml_coll_t bmodule(x_det_modules, _U(trap)); bmodule != nullptr;
234  ++bmodule) {
235  xml_comp_t x_det_trap = bmodule;
236 
237  // Due to convention this causes an axis flip on x
238  Trapezoid trapShape(0.5 * x_det_trap.dz(), 0.5 * x_det_trap.dz(),
239  x_det_trap.x1(), x_det_trap.x2(),
240  0.5 * x_det_trap.dy());
241 
242  // Set an orientation
243  DetElement trapElement(detName + "_module" + std::to_string(sensorID),
244  sensorID);
245  auto &params =
246  DD4hepTestsHelper::ensureExtension<dd4hep::rec::VariantParameters>(
247  trapElement);
248  params.set<std::string>("axis_definitions", "YZ");
249 
250  Volume trapVolume(detName, trapShape,
251  dd.material(x_det_trap.materialStr()));
252  trapVolume.setVisAttributes(dd, x_det.visStr());
253  trapVolume.setSensitiveDetector(sens);
254 
255  PlacedVolume placedTrap = envelopeVolume.placeVolume(
256  trapVolume, DD4hepTestsHelper::createTransform(x_det_trap));
257 
258  placedTrap.addPhysVolID("sensor", sensorID++);
259  trapElement.setPlacement(placedTrap);
260  // Add the module elements
261  discLayerElement.add(trapElement);
262  }
263  }
264 
265  // Place the envelope into mother
266  Volume motherVolume = dd.pickMotherVolume(discLayerElement);
267  PlacedVolume placedEnvelope = motherVolume.placeVolume(
268  envelopeVolume, DD4hepTestsHelper::createTransform(x_det_env));
269  placedEnvelope.addPhysVolID("system", discLayerElement.id());
270  discLayerElement.setPlacement(placedEnvelope);
271 
272  return discLayerElement;
273 }
274 
275 DECLARE_DETELEMENT(DiscLayer, create_disc_layer)