Belle II Software  release-08-01-10
GeoPXDCreator.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <pxd/geometry/GeoPXDCreator.h>
10 #include <vxd/geometry/GeoCache.h>
11 #include <pxd/geometry/SensorInfo.h>
12 #include <pxd/simulation/SensitiveDetector.h>
13 
14 #include <simulation/background/BkgSensitiveDetector.h>
15 
16 #include <geometry/Materials.h>
17 #include <geometry/CreatorFactory.h>
18 #include <geometry/utilities.h>
19 #include <framework/gearbox/GearDir.h>
20 #include <framework/gearbox/Unit.h>
21 #include <framework/logging/Logger.h>
22 
23 #include <cmath>
24 #include <boost/format.hpp>
25 
26 #include <G4LogicalVolume.hh>
27 #include <G4PVPlacement.hh>
28 
29 //Shapes
30 #include <G4Box.hh>
31 #include <G4Tubs.hh>
32 #include <G4Polycone.hh>
33 #include <G4SubtractionSolid.hh>
34 #include <G4Region.hh>
35 
36 using namespace std;
37 using namespace boost;
38 
39 namespace Belle2 {
44  using namespace geometry;
46  namespace PXD {
47 
50 
51  GeoPXDCreator::~GeoPXDCreator()
52  {
53  for (SensorInfo* sensorInfo : m_SensorInfo) delete sensorInfo;
54  m_SensorInfo.clear();
55  }
56 
57  VXD::SensorInfoBase* GeoPXDCreator::createSensorInfo(const VXDGeoSensorPar& sensor)
58  {
59 
60  const PXDSensorInfoPar& infoPar = dynamic_cast<const PXDSensorInfoPar&>(*sensor.getSensorInfo());
61 
62  SensorInfo* info = new SensorInfo(
63  VxdID(0, 0, 0),
64  infoPar.getWidth(),
65  infoPar.getLength(),
66  infoPar.getThickness(),
67  infoPar.getUCells(),
68  infoPar.getVCells1(),
69  infoPar.getSplitLength(),
70  infoPar.getVCells2()
71  );
72  info->setDEPFETParams(
73  infoPar.getBulkDoping() / (Unit::um * Unit::um * Unit::um),
74  infoPar.getBackVoltage(),
75  infoPar.getTopVoltage(),
76  infoPar.getSourceBorderSmallPitch(),
77  infoPar.getClearBorderSmallPitch(),
78  infoPar.getDrainBorderSmallPitch(),
79  infoPar.getSourceBorderLargePitch(),
80  infoPar.getClearBorderLargePitch(),
81  infoPar.getDrainBorderLargePitch(),
82  infoPar.getGateDepth(),
83  infoPar.getDoublePixel(),
84  infoPar.getChargeThreshold(),
85  infoPar.getNoiseFraction()
86  );
87  info->setIntegrationWindow(
88  infoPar.getIntegrationStart(),
89  infoPar.getIntegrationEnd()
90  );
91 
92  m_SensorInfo.push_back(info);
93  return info;
94  }
95 
96  PXDSensorInfoPar* GeoPXDCreator::readSensorInfo(const GearDir& sensor)
97  {
99  VxdID(0, 0, 0),
100  sensor.getLength("width"),
101  sensor.getLength("length"),
102  sensor.getLength("height"),
103  sensor.getInt("pixelsU"),
104  sensor.getInt("pixelsV[1]"),
105  sensor.getLength("splitLength", 0),
106  sensor.getInt("pixelsV[2]", 0)
107  );
108 
109  info->setDEPFETParams(
110  sensor.getDouble("BulkDoping"),
111  sensor.getWithUnit("BackVoltage"),
112  sensor.getWithUnit("TopVoltage"),
113  sensor.getLength("SourceBorderSmallPixel"),
114  sensor.getLength("ClearBorderSmallPixel"),
115  sensor.getLength("DrainBorderSmallPixel"),
116  sensor.getLength("SourceBorderLargePixel"),
117  sensor.getLength("ClearBorderLargePixel"),
118  sensor.getLength("DrainBorderLargePixel"),
119  sensor.getLength("GateDepth"),
120  sensor.getBool("DoublePixel"),
121  sensor.getDouble("ChargeThreshold"),
122  sensor.getDouble("NoiseFraction")
123  );
124  info->setIntegrationWindow(
125  sensor.getTime("IntegrationStart"),
126  sensor.getTime("IntegrationEnd")
127  );
128  return info;
129  }
130 
131 
132  PXDGeometryPar GeoPXDCreator::createConfiguration(const GearDir& content)
133  {
134  // Create an empty payload
135  PXDGeometryPar pxdGeometryPar;
136 
137  //Read prefix ('SVD' or 'PXD')
138  pxdGeometryPar.setPrefix(m_prefix);
139 
140  //Read some global parameters
141  VXDGlobalPar globals((float)content.getDouble("ElectronTolerance", 100),
142  (float)content.getDouble("MinimumElectrons", 10),
143  content.getLength("ActiveStepSize", 0.005),
144  content.getBool("ActiveChips", false),
145  content.getBool("SeeNeutrons", false),
146  content.getBool("OnlyPrimaryTrueHits", false),
147  content.getBool("OnlyActiveMaterial", false),
148  (float)content.getLength("DistanceTolerance", 0.005),
149  content.getString("DefaultMaterial", "Air")
150  );
151  pxdGeometryPar.setGlobalParams(globals);
152 
153  //Read envelope parameters
154  GearDir envelopeParams(content, "Envelope/");
155  VXDEnvelopePar envelope(envelopeParams.getString("Name", ""),
156  envelopeParams.getString("Material", "Air"),
157  envelopeParams.getString("Color", ""),
158  envelopeParams.getAngle("minPhi", 0),
159  envelopeParams.getAngle("maxPhi", 2 * M_PI),
160  (envelopeParams.getNodes("InnerPoints/point").size() > 0)
161  );
162 
163  for (const GearDir& point : envelopeParams.getNodes("InnerPoints/point")) {
164  pair<double, double> ZXPoint(point.getLength("z"), point.getLength("x"));
165  envelope.getInnerPoints().push_back(ZXPoint);
166  }
167  for (const GearDir& point : envelopeParams.getNodes("OuterPoints/point")) {
168  pair<double, double> ZXPoint(point.getLength("z"), point.getLength("x"));
169  envelope.getOuterPoints().push_back(ZXPoint);
170  }
171  pxdGeometryPar.setEnvelope(envelope);
172 
173  // Read alignment for detector m_prefix ('PXD' or 'SVD')
174  string pathAlign = (boost::format("Align[@component='%1%']/") % m_prefix).str();
175  GearDir paramsAlign(GearDir(content, "Alignment/"), pathAlign);
176  if (!paramsAlign) {
177  B2WARNING("Could not find alignment parameters for component " << m_prefix);
178  return pxdGeometryPar;
179  }
180  pxdGeometryPar.getAlignmentMap()[m_prefix] = VXDAlignmentPar(paramsAlign.getLength("du"),
181  paramsAlign.getLength("dv"),
182  paramsAlign.getLength("dw"),
183  paramsAlign.getAngle("alpha"),
184  paramsAlign.getAngle("beta"),
185  paramsAlign.getAngle("gamma")
186  );
187 
188  //Read the definition of all sensor types
189  GearDir components(content, "Components/");
190  for (const GearDir& paramsSensor : components.getNodes("Sensor")) {
191  string sensorTypeID = paramsSensor.getString("@type");
192 
193  VXDGeoSensorPar sensor(paramsSensor.getString("Material"),
194  paramsSensor.getString("Color", ""),
195  paramsSensor.getLength("width"),
196  paramsSensor.getLength("width2", 0),
197  paramsSensor.getLength("length"),
198  paramsSensor.getLength("height"),
199  paramsSensor.getAngle("angle", 0),
200  paramsSensor.getBool("@slanted", false)
201  );
202  sensor.setActive(VXDGeoComponentPar(
203  paramsSensor.getString("Material"),
204  paramsSensor.getString("Active/Color", "#f00"),
205  paramsSensor.getLength("Active/width"),
206  paramsSensor.getLength("Active/width2", 0),
207  paramsSensor.getLength("Active/length"),
208  paramsSensor.getLength("Active/height")
210  "Active",
211  paramsSensor.getLength("Active/u"),
212  paramsSensor.getLength("Active/v"),
213  paramsSensor.getString("Active/w", "center"),
214  paramsSensor.getLength("Active/woffset", 0)
215  ));
216 
217  PXDSensorInfoPar* pxdInfo = readSensorInfo(GearDir(paramsSensor, "Active"));
218  sensor.setSensorInfo(pxdInfo);
219  sensor.setComponents(getSubComponents(paramsSensor));
220  pxdGeometryPar.getSensorMap()[sensorTypeID] = sensor;
221  pxdGeometryPar.getSensorInfos().push_back(pxdInfo);
222  }
223 
224  //Build all ladders including Sensors
225  GearDir support(content, "Support/");
226  readHalfShellSupport(support, pxdGeometryPar);
227 
228  for (const GearDir& shell : content.getNodes("HalfShell")) {
229 
230  string shellName = m_prefix + "." + shell.getString("@name");
231  string pathShell = (boost::format("Align[@component='%1%']/") % shellName).str();
232  GearDir paramsShell(GearDir(content, "Alignment/"), pathShell);
233  if (!paramsShell) {
234  B2WARNING("Could not find alignment parameters for component " << shellName);
235  return pxdGeometryPar;
236  }
237  pxdGeometryPar.getAlignmentMap()[shellName] = VXDAlignmentPar(paramsShell.getLength("du"),
238  paramsShell.getLength("dv"),
239  paramsShell.getLength("dw"),
240  paramsShell.getAngle("alpha"),
241  paramsShell.getAngle("beta"),
242  paramsShell.getAngle("gamma")
243  );
244 
245  VXDHalfShellPar halfShell(shell.getString("@name"), shell.getAngle("shellAngle", 0));
246 
247  for (const GearDir& layer : shell.getNodes("Layer")) {
248  int layerID = layer.getInt("@id");
249 
250  readLadder(layerID, components, pxdGeometryPar);
251 
252  //Loop over defined ladders
253  for (const GearDir& ladder : layer.getNodes("Ladder")) {
254  int ladderID = ladder.getInt("@id");
255  double phi = ladder.getAngle("phi", 0);
256  readLadderComponents(layerID, ladderID, content, pxdGeometryPar);
257  halfShell.addLadder(layerID, ladderID, phi);
258  }
259  }
260  pxdGeometryPar.getHalfShells().push_back(halfShell);
261  }
262 
263  //Create diamond radiation sensors if defined and in background mode
264  GearDir radiationDir(content, "RadiationSensors");
265  if (pxdGeometryPar.getGlobalParams().getActiveChips() && radiationDir) {
266  VXDGeoRadiationSensorsPar radiationSensors(
267  m_prefix,
268  radiationDir.getBool("insideEnvelope"),
269  radiationDir.getLength("width"),
270  radiationDir.getLength("length"),
271  radiationDir.getLength("height"),
272  radiationDir.getString("material")
273  );
274 
275  //Add radiation sensor positions
276  for (GearDir& position : radiationDir.getNodes("position")) {
277  VXDGeoRadiationSensorsPositionPar diamonds(position.getLength("z"),
278  position.getLength("radius"),
279  position.getAngle("theta")
280  );
281 
282  //Loop over all phi positions
283  for (GearDir& sensor : position.getNodes("phi")) {
284  //Add sensor with angle and id
285  diamonds.addSensor(sensor.getInt("@id"), sensor.getAngle());
286  }
287  radiationSensors.addPosition(diamonds);
288  }
289  pxdGeometryPar.setRadiationSensors(radiationSensors);
290  }
291 
292  return pxdGeometryPar;
293  }
294 
295  void GeoPXDCreator::readHalfShellSupport(const GearDir& support, PXDGeometryPar& pxdGeometryPar)
296  {
297  for (const GearDir& endflange : support.getNodes("Endflange")) {
298  VXDPolyConePar endflangePar(
299  endflange.getString("@name"),
300  endflange.getString("Material", "Air"),
301  endflange.getAngle("minPhi", 0),
302  endflange.getAngle("maxPhi", 2 * M_PI),
303  (endflange.getNodes("Cutout").size() > 0),
304  endflange.getLength("Cutout/width1", 0.),
305  endflange.getLength("Cutout/width2", 0.),
306  endflange.getLength("Cutout/height", 0.),
307  endflange.getLength("Cutout/depth", 0.)
308  );
309 
310  for (const GearDir& plane : endflange.getNodes("Plane")) {
311  VXDPolyConePlanePar planePar(
312  plane.getLength("posZ"),
313  plane.getLength("innerRadius"),
314  plane.getLength("outerRadius")
315  );
316  endflangePar.getPlanes().push_back(planePar);
317  }
318  pxdGeometryPar.getEndflanges().push_back(endflangePar);
319  }
320 
321  // Cout outs for endflanges
322  pxdGeometryPar.setNCutOuts(support.getInt("Cutout/count"));
323  pxdGeometryPar.setCutOutWidth(support.getLength("Cutout/width"));
324  pxdGeometryPar.setCutOutHeight(support.getLength("Cutout/height"));
325  pxdGeometryPar.setCutOutShift(support.getLength("Cutout/shift"));
326  pxdGeometryPar.setCutOutRPhi(support.getLength("Cutout/rphi"));
327  pxdGeometryPar.setCutOutStartPhi(support.getAngle("Cutout/startPhi"));
328  pxdGeometryPar.setCutOutDeltaPhi(support.getAngle("Cutout/deltaPhi"));
329 
330  //Create Carbon cooling tubes
331  pxdGeometryPar.setNTubes(support.getInt("CarbonTubes/count"));
332  pxdGeometryPar.setTubesMinZ(support.getLength("CarbonTubes/minZ"));
333  pxdGeometryPar.setTubesMaxZ(support.getLength("CarbonTubes/maxZ"));
334  pxdGeometryPar.setTubesMinR(support.getLength("CarbonTubes/innerRadius"));
335  pxdGeometryPar.setTubesMaxR(support.getLength("CarbonTubes/outerRadius"));
336  pxdGeometryPar.setTubesRPhi(support.getLength("CarbonTubes/rphi"));
337  pxdGeometryPar.setTubesStartPhi(support.getAngle("CarbonTubes/startPhi"));
338  pxdGeometryPar.setTubesDeltaPhi(support.getAngle("CarbonTubes/deltaPhi"));
339  pxdGeometryPar.setTubesMaterial(support.getString("CarbonTubes/Material", "Carbon"));
340 
341  return;
342  }
343 
344  void GeoPXDCreator::createGeometry(const PXDGeometryPar& parameters, G4LogicalVolume& topVolume, geometry::GeometryTypes)
345  {
346 
347  m_activeStepSize = parameters.getGlobalParams().getActiveStepSize() / Unit::mm;
348  m_activeChips = parameters.getGlobalParams().getActiveChips();
349  m_seeNeutrons = parameters.getGlobalParams().getSeeNeutrons();
350  m_onlyPrimaryTrueHits = parameters.getGlobalParams().getOnlyPrimaryTrueHits();
351  m_distanceTolerance = parameters.getGlobalParams().getDistanceTolerance();
352  m_electronTolerance = parameters.getGlobalParams().getElectronTolerance();
353  m_minimumElectrons = parameters.getGlobalParams().getMinimumElectrons();
354  m_onlyActiveMaterial = parameters.getGlobalParams().getOnlyActiveMaterial();
355  m_defaultMaterial = parameters.getGlobalParams().getDefaultMaterial();
356 
357  G4Material* material = Materials::get(m_defaultMaterial);
358  if (!material) B2FATAL("Default Material of VXD, '" << m_defaultMaterial << "', could not be found");
359 
360 
361  //Build envelope
362  G4LogicalVolume* envelope(0);
363  G4VPhysicalVolume* physEnvelope{nullptr};
364  if (!parameters.getEnvelope().getExists()) {
365  B2INFO("Could not find definition for " + m_prefix + " Envelope, placing directly in top volume");
366  envelope = &topVolume;
367  } else {
368  double minZ(0), maxZ(0);
369  G4Polycone* envelopeCone = geometry::createRotationSolid("Envelope",
370  parameters.getEnvelope().getInnerPoints(),
371  parameters.getEnvelope().getOuterPoints(),
372  parameters.getEnvelope().getMinPhi(),
373  parameters.getEnvelope().getMaxPhi(),
374  minZ, maxZ
375  );
376  envelope = new G4LogicalVolume(envelopeCone, material, m_prefix + ".Envelope");
377  setVisibility(*envelope, false);
378  physEnvelope = new G4PVPlacement(getAlignment(parameters.getAlignment(m_prefix)), envelope, m_prefix + ".Envelope",
379  &topVolume, false, 1);
380 
381  // Set up region for production cuts
382  G4Region* aRegion = new G4Region("PXDEnvelope");
383  envelope->SetRegion(aRegion);
384  aRegion->AddRootLogicalVolume(envelope);
385  }
386 
387  //Read the definition of all sensor types
388  for (const pair<const string, VXDGeoSensorPar>& typeAndSensor : parameters.getSensorMap()) {
389  const string& sensorTypeID = typeAndSensor.first;
390  const VXDGeoSensorPar& paramsSensor = typeAndSensor.second;
391  VXDGeoSensor sensor(
392  paramsSensor.getMaterial(),
393  paramsSensor.getColor(),
394  paramsSensor.getWidth() / Unit::mm,
395  paramsSensor.getWidth2() / Unit::mm,
396  paramsSensor.getLength() / Unit::mm,
397  paramsSensor.getHeight() / Unit::mm,
398  paramsSensor.getSlanted()
399  );
400  sensor.setActive(VXDGeoComponent(
401  paramsSensor.getMaterial(),
402  paramsSensor.getActiveArea().getColor(),
403  paramsSensor.getActiveArea().getWidth() / Unit::mm,
404  paramsSensor.getActiveArea().getWidth2() / Unit::mm,
405  paramsSensor.getActiveArea().getLength() / Unit::mm,
406  paramsSensor.getActiveArea().getHeight() / Unit::mm
407  ), VXDGeoPlacement(
408  "Active",
409  paramsSensor.getActivePlacement().getU() / Unit::mm,
410  paramsSensor.getActivePlacement().getV() / Unit::mm,
411  paramsSensor.getActivePlacement().getW(),
412  paramsSensor.getActivePlacement().getWOffset() / Unit::mm
413  ));
414  sensor.setSensorInfo(createSensorInfo(paramsSensor));
415 
416  vector<VXDGeoPlacement> subcomponents;
417  const auto& components = paramsSensor.getComponents();
418  subcomponents.reserve(components.size());
419  std::transform(components.begin(), components.end(), std::back_inserter(subcomponents),
420  [](auto const & component) {
421  return VXDGeoPlacement(component.getName(),
422  component.getU() / Unit::mm,
423  component.getV() / Unit::mm,
424  component.getW(),
425  component.getWOffset() / Unit::mm
426  );
427  });
428  sensor.setComponents(subcomponents);
429  m_sensorMap[sensorTypeID] = sensor;
430  }
431 
432  //Read the component cache from DB
433  for (const string& name : parameters.getComponentInsertOder()) {
434  if (m_componentCache.find(name) != m_componentCache.end()) {
435  // already created due to being a sub component of a previous
436  // component. Seems fishy since the information of this component
437  // is in the db at least twice so we could run into
438  // inconsistencies.
439  B2WARNING("Component " << name << " already created from previous subcomponents, should not be here");
440  continue;
441  }
442  const VXDGeoComponentPar& paramsComponent = parameters.getComponent(name);
443  VXDGeoComponent c(
444  paramsComponent.getMaterial(),
445  paramsComponent.getColor(),
446  paramsComponent.getWidth() / Unit::mm,
447  paramsComponent.getWidth2() / Unit::mm,
448  paramsComponent.getLength() / Unit::mm,
449  paramsComponent.getHeight() / Unit::mm
450  );
451  double angle = paramsComponent.getAngle();
452 
453 
454  if (c.getWidth() <= 0 || c.getLength() <= 0 || c.getHeight() <= 0) {
455  B2DEBUG(100, "One dimension empty, using auto resize for component");
456  } else {
457  G4VSolid* solid = createTrapezoidal(m_prefix + "." + name, c.getWidth(), c.getWidth2(), c.getLength(), c.getHeight(), angle);
458  c.setVolume(new G4LogicalVolume(solid, Materials::get(c.getMaterial()), m_prefix + "." + name));
459  }
460 
461  vector<VXDGeoPlacement> subComponents;
462  const auto& paramsSubComponents = paramsComponent.getSubComponents();
463  subComponents.reserve(paramsSubComponents.size());
464  std::transform(paramsSubComponents.begin(), paramsSubComponents.end(), std::back_inserter(subComponents),
465  [](auto const & paramsSubComponent) {
466  return VXDGeoPlacement(paramsSubComponent.getName(),
467  paramsSubComponent.getU() / Unit::mm,
468  paramsSubComponent.getV() / Unit::mm,
469  paramsSubComponent.getW(),
470  paramsSubComponent.getWOffset() / Unit::mm
471  );
472  });
473  createSubComponents(m_prefix + "." + name, c, subComponents);
474  if (m_activeChips && parameters.getSensitiveChipID(name) >= 0) {
475  int chipID = parameters.getSensitiveChipID(name);
476  B2DEBUG(50, "Creating BkgSensitiveDetector for component " << name << " with chipID " << chipID);
477  BkgSensitiveDetector* sensitive = new BkgSensitiveDetector(m_prefix.c_str(), chipID);
478  c.getVolume()->SetSensitiveDetector(sensitive);
479  m_sensitive.push_back(sensitive);
480  }
481 
482  m_componentCache[name] = c;
483  }
484 
485  //Build all ladders including Sensors
486  VXD::GeoVXDAssembly shellSupport = createHalfShellSupport(parameters);
487 
488  //const std::vector<VXDHalfShellPar>& HalfShells = parameters.getHalfShells();
489  for (const VXDHalfShellPar& shell : parameters.getHalfShells()) {
490  string shellName = shell.getName();
491  m_currentHalfShell = m_prefix + "." + shellName;
492  G4Transform3D shellAlignment = getAlignment(parameters.getAlignment(m_currentHalfShell));
493 
494  // Remember shell coordinate system (into which ladders are inserted)
495  VXD::GeoCache::getInstance().addHalfShellPlacement(m_halfShellVxdIDs[m_currentHalfShell], shellAlignment);
496 
497  //Place shell support
498  double shellAngle = shell.getShellAngle(); // Only used to move support, not active volumes!
499  if (!m_onlyActiveMaterial) shellSupport.place(envelope, shellAlignment * G4RotateZ3D(shellAngle));
500 
501  //const std::map< int, std::vector<std::pair<int, double>> >& Layers = shell.getLayers();
502  for (const std::pair<const int, std::vector<std::pair<int, double>> >& layer : shell.getLayers()) {
503  int layerID = layer.first;
504  const std::vector<std::pair<int, double>>& Ladders = layer.second;
505 
506 
507  setCurrentLayer(layerID, parameters);
508 
509  //Place Layer support
510  VXD::GeoVXDAssembly layerSupport = createLayerSupport();
511  if (!m_onlyActiveMaterial) layerSupport.place(envelope, shellAlignment * G4RotateZ3D(shellAngle));
512  VXD::GeoVXDAssembly ladderSupport = createLadderSupport();
513 
514  //Loop over defined ladders
515  for (const std::pair<int, double>& ladder : Ladders) {
516  int ladderID = ladder.first;
517  double phi = ladder.second;
518 
519  G4Transform3D ladderPlacement = placeLadder(ladderID, phi, envelope, shellAlignment, parameters);
520  if (!m_onlyActiveMaterial) ladderSupport.place(envelope, ladderPlacement);
521  }
522 
523  }
524  }
525 
526  //Now build cache with all transformations
527  if (physEnvelope) {
528  VXD::GeoCache::getInstance().findVolumes(physEnvelope);
529  } else {
530  //create a temporary placement of the top volume.
531  G4PVPlacement topPlacement(nullptr, G4ThreeVector(0, 0, 0), &topVolume,
532  "temp_Top", nullptr, false, 1, false);
533  //and search for all VXD sensitive sensors within
534  VXD::GeoCache::getInstance().findVolumes(&topPlacement);
535  }
536 
537  //Create diamond radiation sensors if defined and in background mode
538  if (m_activeChips) {
539  if (parameters.getRadiationSensors().getSubDetector() == "") {
540  B2DEBUG(10, "Apparently no radiation sensors defined, skipping");
541  } else {
542  createDiamonds(parameters.getRadiationSensors(), topVolume, *envelope);
543  }
544  }
545  }
546 
547  VXD::SensitiveDetectorBase* GeoPXDCreator::createSensitiveDetector(VxdID sensorID, const VXDGeoSensor& sensor,
548  const VXDGeoSensorPlacement& placement)
549  {
550  SensorInfo* sensorInfo = new SensorInfo(dynamic_cast<const SensorInfo&>(*sensor.getSensorInfo()));
551  sensorInfo->setID(sensorID);
552  if (placement.getFlipV()) sensorInfo->flipVSegmentation();
553  SensitiveDetector* sensitive = new SensitiveDetector(sensorInfo);
554  return sensitive;
555  }
556 
557  VXD::GeoVXDAssembly GeoPXDCreator::createLayerSupport() { return VXD::GeoVXDAssembly(); }
558 
559  VXD::GeoVXDAssembly GeoPXDCreator::createLadderSupport() { return VXD::GeoVXDAssembly(); }
560 
561  VXD::GeoVXDAssembly GeoPXDCreator::createHalfShellSupport(const PXDGeometryPar& parameters)
562  {
563  VXD::GeoVXDAssembly supportAssembly;
564 
565  if (!parameters.getBuildSupport()) return supportAssembly;
566 
567 
568  // Create the Endlanges
569  const std::vector<VXDPolyConePar> Endflanges = parameters.getEndflanges();
570  for (const VXDPolyConePar& endflange : Endflanges) {
571 
572  double minZ(0), maxZ(0);
573  string name = endflange.getName();
574 
575  // Create a polycone
576  double minPhi = endflange.getMinPhi();
577  double dPhi = endflange.getMaxPhi() - minPhi;
578  int nPlanes = endflange.getPlanes().size();
579  if (nPlanes < 2) {
580  B2ERROR("Polycone needs at least two planes");
581  return supportAssembly;
582  }
583  std::vector<double> z(nPlanes, 0);
584  std::vector<double> rMin(nPlanes, 0);
585  std::vector<double> rMax(nPlanes, 0);
586  int index(0);
587  minZ = numeric_limits<double>::infinity();
588  maxZ = -numeric_limits<double>::infinity();
589 
590  const std::vector<VXDPolyConePlanePar> Planes = endflange.getPlanes();
591  for (const VXDPolyConePlanePar& plane : Planes) {
592  z[index] = plane.getPosZ() / Unit::mm;
593  minZ = min(minZ, z[index]);
594  maxZ = max(maxZ, z[index]);
595  rMin[index] = plane.getInnerRadius() / Unit::mm;
596  rMax[index] = plane.getOuterRadius() / Unit::mm;
597  ++index;
598  }
599 
600  G4VSolid* supportCone = new G4Polycone(name, minPhi, dPhi, nPlanes, z.data(), rMin.data(), rMax.data());
601 
602 
603  //Cutout boxes to make place for modules
604 
605  //We have the z dimensions of the polycon. Let's
606  //add 1mm on each side to make sure we don't run into problems when the
607  //surfaces match
608  minZ -= 1. / Unit::mm;
609  maxZ += 1. / Unit::mm;
610 
611 
612  //Now get the number of cutouts and their size/position/angle
613  int nCutouts = parameters.getNCutOuts();
614  double sizeX = parameters.getCutOutWidth() / Unit::mm / 2.;
615  double sizeY = parameters.getCutOutHeight() / Unit::mm / 2.;
616  double sizeZ = (maxZ - minZ) / 2.;
617  G4ThreeVector origin(
618  parameters.getCutOutShift() / Unit::mm,
619  parameters.getCutOutRPhi() / Unit::mm,
620  minZ + sizeZ
621  );
622 
623  double phi0 = parameters.getCutOutStartPhi();
624  double dphi = parameters.getCutOutDeltaPhi();
625  for (int i = 0; i < nCutouts; ++i) {
626  G4Box* box = new G4Box("Cutout", sizeX, sizeY, sizeZ);
627  G4Transform3D placement = G4RotateZ3D(phi0 + i * dphi) * G4Translate3D(origin);
628  G4VSolid* supportConeOld = supportCone;
629  supportCone = new G4SubtractionSolid("PXD Support endflange", supportConeOld, box, placement);
630  }
631 
632 
633  string materialName = endflange.getMaterial();
634  G4Material* material = geometry::Materials::get(materialName);
635  if (!material) B2FATAL("Material '" << materialName << "', required by PXD component " << name << ", could not be found");
636 
637  G4LogicalVolume* volume = new G4LogicalVolume(supportCone, material, name);
638  geometry::setColor(*volume, "#ccc4");
639  supportAssembly.add(volume);
640 
641  }
642 
643 
644  //Create Carbon cooling tubes
645  {
646  int nTubes = parameters.getNTubes();
647  double minZ = parameters.getTubesMinZ() / Unit::mm;
648  double maxZ = parameters.getTubesMaxZ() / Unit::mm;
649  double minR = parameters.getTubesMinR() / Unit::mm;
650  double maxR = parameters.getTubesMaxR() / Unit::mm;
651  double sizeZ = (maxZ - minZ) / 2.;
652  double shiftX = parameters.getTubesRPhi() / Unit::mm;
653  double shiftY = 0;
654  double shiftZ = minZ + sizeZ;
655  double phi0 = parameters.getTubesStartPhi();
656  double dphi = parameters.getTubesDeltaPhi();
657  string material = parameters.getTubesMaterial();
658 
659  G4Tubs* tube = new G4Tubs("CarbonTube", minR, maxR, sizeZ, 0, 2 * M_PI);
660  G4LogicalVolume* tubeVol = new G4LogicalVolume(tube, geometry::Materials::get(material), "CarbonTube");
661  geometry::setColor(*tubeVol, "#000");
662  for (int i = 0; i < nTubes; ++i) {
663  G4Transform3D placement = G4RotateZ3D(phi0 + i * dphi) * G4Translate3D(shiftX, shiftY, shiftZ);
664  supportAssembly.add(tubeVol, placement);
665  }
666  }
667 
668  return supportAssembly;
669  }
670 
671 
672  }
674 }
The Class for BeamBackground Sensitive Detector.
GearDir is the basic class used for accessing the parameter store.
Definition: GearDir.h:31
virtual std::string getString(const std::string &path="") const noexcept(false) override
Get the parameter path as a string.
Definition: GearDir.h:69
The Class for VXD geometry.
void setNTubes(int nTubes)
set number of tubes
void setTubesRPhi(double rphi)
set tubes tubes RPhi
void setTubesMaxR(double maxR)
set tubes maxR
void setNCutOuts(int nCutouts)
set number of cutouts
const std::vector< VXDPolyConePar > & getEndflanges() const
get Endflanges
void setCutOutShift(double shift)
set shift of cutouts
std::vector< PXDSensorInfoPar * > & getSensorInfos()
get sensorInfos
void setCutOutWidth(double width)
set width of cutouts
void setTubesMinZ(double minZ)
set tubes minZ
void setCutOutHeight(double height)
set height of cutouts
void setCutOutDeltaPhi(double delta)
set deltaphi of cutouts
void setTubesDeltaPhi(double delta)
set tubes tubes DeltaPhi
void setTubesMaxZ(double maxZ)
set tubes maxZ
void setTubesMinR(double minR)
set tubes minR
void setCutOutStartPhi(double start)
set start phi of cutouts
void setCutOutRPhi(double rphi)
set rphi of cutouts
void setTubesStartPhi(double start)
set tubes tubes StartPhi
void setTubesMaterial(const std::string &material)
set tubes tubes material
The Class for VXD geometry.
double getTopVoltage() const
Return the voltage at the top of the sensor.
double getClearBorderSmallPitch() const
Return the distance along u between the clear side of a small pixel and the start of the internal gat...
double getChargeThreshold() const
Get the charge threshold in ADU for the sensor.
double getGateDepth() const
Return the gate depth for the sensor.
double getDrainBorderLargePitch() const
Return the distance along v between the drain side of a large pixel and the start of the internal gat...
double getClearBorderLargePitch() const
Return the distance along u between the clear side of a large pixel and the start of the internal gat...
double getNoiseFraction() const
Get the noise fraction for the sensor.
double getBulkDoping() const
Return the bulk doping of the Silicon sensor.
bool getDoublePixel() const
Return true if the Sensor is a double pixel structure: every other pixel is mirrored along v.
double getSourceBorderSmallPitch() const
Return the distance along v between the source side of a small pixel and the start of the internal ga...
double getSourceBorderLargePitch() const
Return the distance along v between the source side of a large pixel and the start of the internal ga...
double getIntegrationEnd() const
Return the end of the integration window, the timeframe the PXD is sensitive.
double getBackVoltage() const
Return the voltage at the backside of the sensor.
double getIntegrationStart() const
Return the start of the integration window, the timeframe the PXD is sensitive.
double getDrainBorderSmallPitch() const
Return the distance along v between the drain side of a small pixel and the start of the internal gat...
Specific implementation of SensorInfo for PXD Sensors which provides additional pixel specific inform...
Definition: SensorInfo.h:23
void flipVSegmentation()
Flip the Pitch segmentation along v.
Definition: SensorInfo.h:43
void setID(VxdID id)
Change the SensorID, useful to copy the SensorInfo from one sensor and use it for another.
Definition: SensorInfo.h:37
The Class for VXD Alignment payload.
The Class for VXD Envelope parameters.
The Class for VXD geometry component.
double getWidth() const
get the width of the component
double getHeight() const
get the height of the component
double getAngle() const
get the angle of the component
const std::vector< VXDGeoPlacementPar > & getSubComponents() const
get sub components
double getWidth2() const
get the forward width of the component, 0 for rectangular
const std::string & getColor() const
get the name of the color for the component
const std::string & getMaterial() const
get the name of the Material for the component
double getLength() const
get the length of the component
Class holding all parameters for an VXD geometry component.
The Class for VXD placement payload.
double getU() const
get local u coordinate where to place the component
const std::string & getW() const
get local w position where to place the component
double getV() const
get local v coordinate where to place the component
double getWOffset() const
get offset to local w position where to place the component
Class holding all parameters to place a VXD geometry subcomponent.
The Class for VXD Radiation Sensor parameters.
void addPosition(const VXDGeoRadiationSensorsPositionPar &position)
add radiation sensor position
The Class for VXD Radiation Sensor Position parameters.
void addSensor(int id, double phi)
add sensor with individual id
The Class for VXD Sensor payload.
const VXDGeoPlacementPar & getActivePlacement() const
get the placement description for the active area
const std::vector< VXDGeoPlacementPar > & getComponents() const
get the list of sub components
bool getSlanted() const
return wether or not the sensor is slanted (usually only the first sensor in layers 4-6)
const VXDGeoComponentPar & getActiveArea() const
get the component description for the active area
Struct holding the information where a sensor should be placed inside the ladder.
bool getFlipV() const
check whether or not the sensor should be flipped around the V coordinate
Struct holding all parameters for a completeVXD Sensor.
const std::map< std::string, VXDGeoSensorPar > & getSensorMap() const
get sensor map
void setGlobalParams(const VXDGlobalPar &globals)
set global parameters
void setRadiationSensors(const VXDGeoRadiationSensorsPar &diamonds)
set radiation sensor parameters
const VXDGlobalPar & getGlobalParams() const
get global parameters
const std::vector< VXDHalfShellPar > & getHalfShells() const
get half-shell
void setEnvelope(const VXDEnvelopePar &envelope)
set envelope parameters
void setPrefix(const std::string &prefix)
set prefix
std::map< std::string, VXDAlignmentPar > & getAlignmentMap()
get alignmant map
The Class for VXD global paramter payload.
Definition: VXDGlobalPar.h:24
bool getActiveChips() const
Get whether chips are sensitive
Definition: VXDGlobalPar.h:48
The Class for VXD half shell payload.
void addLadder(int layerID, int ladderID, double phi)
add ladder
The Class for VXD PolyCone, possibly with coutouts.
std::vector< VXDPolyConePlanePar > & getPlanes(void)
Get planes.
The Class for VXD Polycone Plane.
const std::list< std::pair< double, double > > & getInnerPoints() const
get inner XZ points
const std::list< std::pair< double, double > > & getOuterPoints() const
get outer XZ points
double getWidth() const
Return the (backward) width of the sensor.
int getUCells() const
Return number of pixel/strips in u direction.
double getThickness() const
Return the thickness of the sensor.
int getVCells2() const
Return number of pixel/strips in v direction for second segment.
double getSplitLength() const
Return the splitLength of the sensor.
int getVCells1() const
Return number of pixel/strips in v direction for first segment.
double getLength() const
Return the length of the sensor.
Class to group some Geant4 volumes and place them all at once with a given transformation matrix.
void place(G4LogicalVolume *mother, const G4Transform3D &transform)
Place all the volumes already added to the assembly in the given mother.
void add(G4LogicalVolume *volume, const G4Transform3D &transform=G4Transform3D())
Add a volume to the assembly.
Base class for Sensitive Detector implementation of PXD and SVD.
Sensitive Detector implementation of PXD and SVD.
Base class to provide Sensor Information for PXD and SVD.
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33
double getAngle(const std::string &path="") const noexcept(false)
Get the parameter path as a double converted to the standard angle unit.
Definition: Interface.h:299
double getLength(const std::string &path="") const noexcept(false)
Get the parameter path as a double converted to the standard length unit.
Definition: Interface.h:259
std::vector< GearDir > getNodes(const std::string &path="") const
Get vector of GearDirs which point to all the nodes the given path evaluates to.
Definition: Interface.cc:21
bool getBool(const std::string &path="") const noexcept(false)
Get the parameter path as a bool.
Definition: Interface.cc:80
int getInt(const std::string &path="") const noexcept(false)
Get the parameter path as a int.
Definition: Interface.cc:60
geometry::CreatorFactory< GeoPXDCreator > GeoPXDFactory("PXDCreator")
Register the creator.
void setVisibility(G4LogicalVolume &volume, bool visible)
Helper function to quickly set the visibility of a given volume.
Definition: utilities.cc:108
GeometryTypes
Flag indiciating the type of geometry to be used.
Abstract base class for different kinds of events.
Very simple class to provide an easy way to register creators with the CreatorManager.