Belle II Software development
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
36using namespace std;
37using namespace boost;
38
39namespace Belle2 {
44 using namespace geometry;
46 namespace PXD {
47
50
52 {
53 for (SensorInfo* sensorInfo : m_SensorInfo) delete sensorInfo;
54 m_SensorInfo.clear();
55 }
56
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(),
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
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
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
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);
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)
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
511 if (!m_onlyActiveMaterial) layerSupport.place(envelope, shellAlignment * G4RotateZ3D(shellAngle));
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) {
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
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
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
558
560
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
const std::vector< VXDPolyConePar > & getEndflanges() const
get Endflanges
void setNCutOuts(int nCutouts)
set number of cutouts
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...
virtual VXD::GeoVXDAssembly createLayerSupport()
Create support structure for a PXD Layer.
void createGeometry(const PXDGeometryPar &parameters, G4LogicalVolume &topVolume, geometry::GeometryTypes type)
Create the geometry from a parameter object.
virtual VXD::SensitiveDetectorBase * createSensitiveDetector(VxdID sensorID, const VXDGeoSensor &sensor, const VXDGeoSensorPlacement &placement) override
Return a SensitiveDetector implementation for a given sensor.
std::vector< SensorInfo * > m_SensorInfo
Vector of points to SensorInfo objects.
void readHalfShellSupport(const GearDir &support, PXDGeometryPar &pxdGeometryPar)
Create support structure for VXD Half Shell, that means everything that does not depend on layer or s...
PXDGeometryPar createConfiguration(const GearDir &param)
Create a parameter object from the Gearbox XML parameters.
PXDSensorInfoPar * readSensorInfo(const GearDir &sensor)
Read the sensor definitions from the gearbox.
virtual ~GeoPXDCreator()
The destructor of the GeoPXDCreator class.
virtual VXD::GeoVXDAssembly createLadderSupport()
Create support structure for a PXD Ladder.
virtual VXD::GeoVXDAssembly createHalfShellSupport(const PXDGeometryPar &parameters)
Create support structure for PXD Half Shell, that means everything that does not depend on layer or s...
virtual VXD::SensorInfoBase * createSensorInfo(const VXDGeoSensorPar &sensor) override
Read the sensor definitions from the database.
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
static const double mm
[millimeters]
Definition: Unit.h:70
static const double um
[micrometers]
Definition: Unit.h:71
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
const std::vector< VXDGeoPlacementPar > & getSubComponents() const
get sub components
const std::string & getColor() const
get the name of the color for the component
double getAngle() const
get the angle of the component
double getWidth2() const
get the forward width of the component, 0 for rectangular
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
double getV() const
get local v coordinate where to place the component
const std::string & getW() const
get local w position 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
const VXDGeoComponentPar & getActiveArea() const
get the component description for the active area
bool getSlanted() const
return wether or not the sensor is slanted (usually only the first sensor in layers 4-6)
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::vector< VXDHalfShellPar > & getHalfShells() const
get half-shell
void setGlobalParams(const VXDGlobalPar &globals)
set global parameters
void setRadiationSensors(const VXDGeoRadiationSensorsPar &diamonds)
set radiation sensor parameters
const std::map< std::string, VXDGeoSensorPar > & getSensorMap() const
get sensor map
void setEnvelope(const VXDEnvelopePar &envelope)
set envelope parameters
const VXDGlobalPar & getGlobalParams() const
get global 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.
void findVolumes(G4VPhysicalVolume *envelope)
Search a given Geometry for Sensors.
Definition: GeoCache.cc:78
static GeoCache & getInstance()
Return a reference to the singleton instance.
Definition: GeoCache.cc:214
void addHalfShellPlacement(VxdID halfShell, const G4Transform3D &placement)
Remember how half-shell is placed into world volume.
Definition: GeoCache.cc:232
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.
std::map< std::string, VXDGeoSensor > m_sensorMap
Map containing Information about all defined sensor types.
float m_minimumElectrons
minimum number of electrons to be deposited by a particle to be saved
G4VSolid * createTrapezoidal(const std::string &name, double width, double width2, double length, double &height, double angle=0)
Create a trapezoidal solid.
virtual void readLadderComponents(int layerID, int ladderID, GearDir content, VXDGeometryPar &vxdGeometryPar)
Read parameters for ladder components and their alignment corresponding to the given ladder id.
void createDiamonds(const VXDGeoRadiationSensorsPar &params, G4LogicalVolume &topVolume, G4LogicalVolume &envelopeVolume)
Create diamond radiation sensors.
std::vector< Simulation::SensitiveDetectorBase * > m_sensitive
List to all created sensitive detector instances.
std::string m_prefix
Prefix to prepend to all volume names.
bool m_onlyActiveMaterial
If this is true, only active Materials will be placed for tracking studies.
double m_activeStepSize
Stepsize to be used inside active volumes.
float m_distanceTolerance
tolerance for Geant4 steps to be merged to a single step
virtual void readLadder(int layer, GearDir components, VXDGeometryPar &geoparameters)
Read parameters for a ladder in layer with given ID from gearbox and layer store them in payload.
std::map< std::string, Belle2::VxdID > m_halfShellVxdIDs
Used for translation of half-shell name into a VxdID to consitently handle it in hierarchy.
bool m_onlyPrimaryTrueHits
If true only create TrueHits from primary particles and ignore secondaries.
float m_electronTolerance
tolerance for the energy deposition in electrons to be merged in a single step
G4Transform3D getAlignment(const VXDAlignmentPar &params)
Get Alignment from paylead object.
GeoVXDAssembly createSubComponents(const std::string &name, VXDGeoComponent &component, std::vector< VXDGeoPlacement > placements, bool originCenter=true, bool allowOutside=false)
Place a list of subcomponents into an component.
std::map< std::string, VXDGeoComponent > m_componentCache
Cache of all previously created components.
G4Transform3D placeLadder(int ladderID, double phi, G4LogicalVolume *volume, const G4Transform3D &placement, const VXDGeometryPar &parameters)
Place ladder corresponding to the given ladder id into volume setLayer has to be called first to set ...
virtual void setCurrentLayer(int layer, const VXDGeometryPar &parameters)
Read parameters for given layer and store in m_ladder.
std::vector< VXDGeoPlacementPar > getSubComponents(const GearDir &path)
Return vector of VXDGeoPlacements with all the components defined inside a given path.
bool m_seeNeutrons
Make sensitive detectors also see neutrons.
std::string m_defaultMaterial
Name of the Material to be used for Air.
bool m_activeChips
Make also chips sensitive.
std::string m_currentHalfShell
Current half-shell being processed (need to know ladder parent for hierarchy)
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
static G4Material * get(const std::string &name)
Find given material.
Definition: Materials.h:63
VXD::SensitiveDetector< PXDSimHit, PXDTrueHit > SensitiveDetector
The PXD Sensitive Detector class.
geometry::CreatorFactory< GeoPXDCreator > GeoPXDFactory("PXDCreator")
Register the creator.
G4Polycone * createRotationSolid(const std::string &name, const GearDir &params, double &minZ, double &maxZ)
Create a solid by roating two polylines around the Z-Axis.
Definition: utilities.cc:203
void setVisibility(G4LogicalVolume &volume, bool visible)
Helper function to quickly set the visibility of a given volume.
Definition: utilities.cc:108
void setColor(G4LogicalVolume &volume, const std::string &color)
Set the color of a logical volume.
Definition: utilities.cc:100
GeometryTypes
Flag indiciating the type of geometry to be used.
Abstract base class for different kinds of events.
STL namespace.
Very simple class to provide an easy way to register creators with the CreatorManager.