Create the geometry from a parameter object.
344 {
345
346 m_activeStepSize = parameters.getGlobalParams().getActiveStepSize() / Unit::mm;
347 m_activeChips = parameters.getGlobalParams().getActiveChips();
348 m_seeNeutrons = parameters.getGlobalParams().getSeeNeutrons();
349 m_onlyPrimaryTrueHits = parameters.getGlobalParams().getOnlyPrimaryTrueHits();
350 m_distanceTolerance = parameters.getGlobalParams().getDistanceTolerance();
351 m_electronTolerance = parameters.getGlobalParams().getElectronTolerance();
352 m_minimumElectrons = parameters.getGlobalParams().getMinimumElectrons();
353 m_onlyActiveMaterial = parameters.getGlobalParams().getOnlyActiveMaterial();
354 m_defaultMaterial = parameters.getGlobalParams().getDefaultMaterial();
355
356 G4Material* material = Materials::get(m_defaultMaterial);
357 if (!material) B2FATAL("Default Material of VXD, '" << m_defaultMaterial << "', could not be found");
358
359
360
361 G4LogicalVolume* envelope(0);
362 G4VPhysicalVolume* physEnvelope{nullptr};
363 if (!parameters.getEnvelope().getExists()) {
364 B2INFO("Could not find definition for " + m_prefix + " Envelope, placing directly in top volume");
365 envelope = &topVolume;
366 } else {
367 double minZ(0), maxZ(0);
368 G4Polycone* envelopeCone = geometry::createRotationSolid("Envelope",
369 parameters.getEnvelope().getInnerPoints(),
370 parameters.getEnvelope().getOuterPoints(),
371 parameters.getEnvelope().getMinPhi(),
372 parameters.getEnvelope().getMaxPhi(),
373 minZ, maxZ
374 );
375 envelope = new G4LogicalVolume(envelopeCone, material, m_prefix + ".Envelope");
377 physEnvelope = new G4PVPlacement(getAlignment(parameters.getAlignment(m_prefix)), envelope, m_prefix + ".Envelope",
378 &topVolume, false, 1);
379
380
381 G4Region* aRegion = new G4Region("PXDEnvelope");
382 envelope->SetRegion(aRegion);
383 aRegion->AddRootLogicalVolume(envelope);
384 }
385
386
387 for (const pair<const string, VXDGeoSensorPar>& typeAndSensor : parameters.getSensorMap()) {
388 const string& sensorTypeID = typeAndSensor.first;
389 const VXDGeoSensorPar& paramsSensor = typeAndSensor.second;
390 VXDGeoSensor sensor(
391 paramsSensor.getMaterial(),
392 paramsSensor.getColor(),
393 paramsSensor.getWidth() / Unit::mm,
394 paramsSensor.getWidth2() / Unit::mm,
395 paramsSensor.getLength() / Unit::mm,
396 paramsSensor.getHeight() / Unit::mm,
397 paramsSensor.getSlanted()
398 );
399 sensor.setActive(VXDGeoComponent(
400 paramsSensor.getMaterial(),
401 paramsSensor.getActiveArea().getColor(),
402 paramsSensor.getActiveArea().getWidth() / Unit::mm,
403 paramsSensor.getActiveArea().getWidth2() / Unit::mm,
404 paramsSensor.getActiveArea().getLength() / Unit::mm,
405 paramsSensor.getActiveArea().getHeight() / Unit::mm
406 ), VXDGeoPlacement(
407 "Active",
408 paramsSensor.getActivePlacement().getU() / Unit::mm,
409 paramsSensor.getActivePlacement().getV() / Unit::mm,
410 paramsSensor.getActivePlacement().getW(),
411 paramsSensor.getActivePlacement().getWOffset() / Unit::mm
412 ));
413 sensor.setSensorInfo(createSensorInfo(paramsSensor));
414
415 vector<VXDGeoPlacement> subcomponents;
416 const auto& components = paramsSensor.getComponents();
417 subcomponents.reserve(components.size());
418 std::transform(components.begin(), components.end(), std::back_inserter(subcomponents),
419 [](auto const & component) {
420 return VXDGeoPlacement(component.getName(),
421 component.getU() / Unit::mm,
422 component.getV() / Unit::mm,
423 component.getW(),
424 component.getWOffset() / Unit::mm
425 );
426 });
427 sensor.setComponents(subcomponents);
428 m_sensorMap[sensorTypeID] = sensor;
429 }
430
431
432 for (const string& name : parameters.getComponentInsertOder()) {
433 if (m_componentCache.find(name) != m_componentCache.end()) {
434
435
436
437
438 B2WARNING("Component " << name << " already created from previous subcomponents, should not be here");
439 continue;
440 }
441 const VXDGeoComponentPar& paramsComponent = parameters.getComponent(name);
442 VXDGeoComponent c(
443 paramsComponent.getMaterial(),
444 paramsComponent.getColor(),
445 paramsComponent.getWidth() / Unit::mm,
446 paramsComponent.getWidth2() / Unit::mm,
447 paramsComponent.getLength() / Unit::mm,
448 paramsComponent.getHeight() / Unit::mm
449 );
450 double angle = paramsComponent.getAngle();
451
452
453 if (c.getWidth() <= 0 || c.getLength() <= 0 || c.getHeight() <= 0) {
454 B2DEBUG(100, "One dimension empty, using auto resize for component");
455 } else {
456 G4VSolid* solid = createTrapezoidal(m_prefix + "." + name, c.getWidth(), c.getWidth2(), c.getLength(), c.getHeight(), angle);
457 c.setVolume(new G4LogicalVolume(solid, Materials::get(c.getMaterial()), m_prefix + "." + name));
458 }
459
460 vector<VXDGeoPlacement> subComponents;
461 const auto& paramsSubComponents = paramsComponent.getSubComponents();
462 subComponents.reserve(paramsSubComponents.size());
463 std::transform(paramsSubComponents.begin(), paramsSubComponents.end(), std::back_inserter(subComponents),
464 [](auto const & paramsSubComponent) {
465 return VXDGeoPlacement(paramsSubComponent.getName(),
466 paramsSubComponent.getU() / Unit::mm,
467 paramsSubComponent.getV() / Unit::mm,
468 paramsSubComponent.getW(),
469 paramsSubComponent.getWOffset() / Unit::mm
470 );
471 });
472 createSubComponents(m_prefix + "." + name, c, subComponents);
473 if (m_activeChips && parameters.getSensitiveChipID(name) >= 0) {
474 int chipID = parameters.getSensitiveChipID(name);
475 B2DEBUG(50, "Creating BkgSensitiveDetector for component " << name << " with chipID " << chipID);
476 BkgSensitiveDetector* sensitive = new BkgSensitiveDetector(m_prefix.c_str(), chipID);
477 c.getVolume()->SetSensitiveDetector(sensitive);
478 m_sensitive.push_back(sensitive);
479 }
480
481 m_componentCache[name] = c;
482 }
483
484
485 VXD::GeoVXDAssembly shellSupport = createHalfShellSupport(parameters);
486
487
488 for (const VXDHalfShellPar& shell : parameters.getHalfShells()) {
489 string shellName = shell.getName();
490 m_currentHalfShell = m_prefix + "." + shellName;
491 G4Transform3D shellAlignment = getAlignment(parameters.getAlignment(m_currentHalfShell));
492
493
494 VXD::GeoCache::getInstance().addHalfShellPlacement(m_halfShellVxdIDs[m_currentHalfShell], shellAlignment);
495
496
497 double shellAngle = shell.getShellAngle();
498 if (!m_onlyActiveMaterial) shellSupport.place(envelope, shellAlignment * G4RotateZ3D(shellAngle));
499
500
501 for (const std::pair<const int, std::vector<std::pair<int, double>> >& layer : shell.getLayers()) {
502 int layerID = layer.first;
503 const std::vector<std::pair<int, double>>& Ladders = layer.second;
504
505
506 setCurrentLayer(layerID, parameters);
507
508
509 VXD::GeoVXDAssembly layerSupport = createLayerSupport();
510 if (!m_onlyActiveMaterial) layerSupport.place(envelope, shellAlignment * G4RotateZ3D(shellAngle));
511 VXD::GeoVXDAssembly ladderSupport = createLadderSupport();
512
513
514 for (const std::pair<int, double>& ladder : Ladders) {
515 int ladderID = ladder.first;
516 double phi = ladder.second;
517
518 G4Transform3D ladderPlacement = placeLadder(ladderID, phi, envelope, shellAlignment, parameters);
519 if (!m_onlyActiveMaterial) ladderSupport.place(envelope, ladderPlacement);
520 }
521
522 }
523 }
524
525
526 if (physEnvelope) {
527 VXD::GeoCache::getInstance().findVolumes(physEnvelope);
528 } else {
529
530 G4PVPlacement topPlacement(nullptr, G4ThreeVector(0, 0, 0), &topVolume,
531 "temp_Top", nullptr, false, 1, false);
532
533 VXD::GeoCache::getInstance().findVolumes(&topPlacement);
534 }
535
536
537 if (m_activeChips) {
538 if (parameters.getRadiationSensors().getSubDetector() == "") {
539 B2DEBUG(10, "Apparently no radiation sensors defined, skipping");
540 } else {
541 createDiamonds(parameters.getRadiationSensors(), topVolume, *envelope);
542 }
543 }
544 }
void setVisibility(G4LogicalVolume &volume, bool visible)
Helper function to quickly set the visibility of a given volume.