//========================================================================== // AIDA Detector description implementation //-------------------------------------------------------------------------- // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) // All rights reserved. // // For the licensing terms see $DD4hepINSTALL/LICENSE. // For the list of contributors see $DD4hepINSTALL/doc/CREDITS. // // Author : M.Frank // //========================================================================== // // Specialized generic detector constructor // //========================================================================== #include <map> #include "DD4hep/DetFactoryHelper.h" #include "Acts/Plugins/DD4hep/ActsExtension.hpp" #include "Acts/Definitions/Units.hpp" using namespace std; using namespace dd4hep; using namespace dd4hep::detail; static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens) { typedef vector<PlacedVolume> Placements; xml_det_t x_det = e; Material vacuum = description.vacuum(); int det_id = x_det.id(); string det_name = x_det.nameStr(); bool reflect = x_det.reflect(false); DetElement sdet(det_name, det_id); Assembly assembly(det_name); Material air = description.material("Air"); // Volume assembly (det_name,Box(10000,10000,10000),vacuum); Volume motherVol = description.pickMotherVolume(sdet); int m_id = 0, c_id = 0, n_sensor = 0; map<string, Volume> modules; map<string, Placements> sensitives; PlacedVolume pv; Acts::ActsExtension* detWorldExt = new Acts::ActsExtension(); detWorldExt->addType("endcap", "detector"); sdet.addExtension<Acts::ActsExtension>(detWorldExt); assembly.setVisAttributes(description.invisible()); sens.setType("tracker"); for (xml_coll_t mi(x_det, _U(module)); mi; ++mi, ++m_id) { xml_comp_t x_mod = mi; string m_nam = x_mod.nameStr(); xml_comp_t trd = x_mod.trd(); double posY; double x1 = trd.x1(); double x2 = trd.x2(); double z = trd.z(); double y1, y2, total_thickness = 0.; xml_coll_t ci(x_mod, _U(module_component)); for (ci.reset(), total_thickness = 0.0; ci; ++ci) total_thickness += xml_comp_t(ci).thickness(); y1 = y2 = total_thickness / 2; Trapezoid m_solid(x1, x2, y1, y2, z); Volume m_volume(m_nam, m_solid, vacuum); m_volume.setVisAttributes(description.visAttributes(x_mod.visStr())); Solid frame_s; if(x_mod.hasChild("frame")){ // build frame from trd (assumed to be smaller) xml_comp_t m_frame = x_mod.child(_U(frame)); xml_comp_t f_pos = m_frame.child(_U(position)); xml_comp_t frame_trd = m_frame.trd(); double frame_thickness = getAttrOrDefault(m_frame, _U(thickness), total_thickness); double frame_x1 = frame_trd.x1(); double frame_x2 = frame_trd.x2(); double frame_z = frame_trd.z(); // make the frame match the total thickness if thickness attribute is not given Trapezoid f_solid1(x1, x2,frame_thickness / 2.0, frame_thickness / 2.0, z); Trapezoid f_solid(frame_x1, frame_x2, frame_thickness / 2.0, frame_thickness / 2.0, frame_z) ; SubtractionSolid frame_shape(f_solid1, f_solid); frame_s = frame_shape; Material f_mat = description.material(m_frame.materialStr()); Volume f_vol(m_nam + "_frame", frame_shape, f_mat); f_vol.setVisAttributes(description.visAttributes(m_frame.visStr())); // figure out how to best place pv = m_volume.placeVolume(f_vol, Position(f_pos.x(), f_pos.y(), f_pos.z())); } for (ci.reset(), n_sensor = 1, c_id = 0, posY = -y1; ci; ++ci, ++c_id) { xml_comp_t c = ci; double c_thick = c.thickness(); auto comp_x1 = getAttrOrDefault(c, _Unicode(x1), x1); auto comp_x2 = getAttrOrDefault(c, _Unicode(x2), x2); auto comp_height = getAttrOrDefault(c, _Unicode(height), z); Material c_mat = description.material(c.materialStr()); string c_name = _toString(c_id, "component%d"); Trapezoid comp_s1(comp_x1, comp_x2, c_thick / 2e0, c_thick / 2e0, comp_height); Solid comp_shape = comp_s1; if(frame_s.isValid()) { comp_shape = SubtractionSolid( comp_s1, frame_s); } Volume c_vol(c_name, comp_shape, c_mat); c_vol.setVisAttributes(description.visAttributes(c.visStr())); pv = m_volume.placeVolume(c_vol, Position(0, posY + c_thick / 2, 0)); if (c.isSensitive()) { sdet.check(n_sensor > 2, "SiTrackerEndcap2::fromCompact: " + c_name + " Max of 2 modules allowed!"); pv.addPhysVolID("sensor", n_sensor); c_vol.setSensitiveDetector(sens); sensitives[m_nam].push_back(pv); ++n_sensor; } posY += c_thick; } modules[m_nam] = m_volume; } for (xml_coll_t li(x_det, _U(layer)); li; ++li) { xml_comp_t x_layer(li); int l_id = x_layer.id(); int mod_num = 1; xml_comp_t l_env = x_layer.child(_U(envelope)); string layer_name = det_name + std::string("_layer") + std::to_string(l_id); std::string layer_vis = l_env.attr<std::string>(_Unicode(vis)); double layer_rmin = l_env.attr<double>(_Unicode(rmin)); double layer_rmax = l_env.attr<double>(_Unicode(rmax)); double layer_length = l_env.attr<double>(_Unicode(length)); double layer_zstart = l_env.attr<double>(_Unicode(zstart)); double layer_center_z = layer_zstart + layer_length/2.0; //printout(INFO,"ROOTGDMLParse","+++ Read geometry from GDML file file:%s",input.c_str()); //std::cout << "SiTracker Endcap layer " << l_id << " zstart = " << layer_zstart/dd4hep::mm << "mm ( " << layer_length/dd4hep::mm << " mm thick )\n"; //Assembly layer_assembly(layer_name); //assembly.placeVolume(layer_assembly); Tube layer_tub(layer_rmin, layer_rmax, layer_length / 2); Volume layer_vol(layer_name, layer_tub, air); // Create the layer envelope volume. layer_vol.setVisAttributes(description.visAttributes(layer_vis)); PlacedVolume layer_pv; if (reflect) { layer_pv = assembly.placeVolume(layer_vol, Transform3D(RotationZYX(0.0, -M_PI, 0.0), Position(0, 0, -layer_center_z))); layer_pv.addPhysVolID("barrel", 3).addPhysVolID("layer", l_id); layer_name += "_N"; } else { layer_pv = assembly.placeVolume(layer_vol, Position(0, 0, layer_center_z)); layer_pv.addPhysVolID("barrel", 2).addPhysVolID("layer", l_id); layer_name += "_P"; } DetElement layer_element(sdet, layer_name, l_id); layer_element.setPlacement(layer_pv); Acts::ActsExtension* layerExtension = new Acts::ActsExtension(); layerExtension->addType("layer", "layer"); //layerExtension->addType("axes", "definitions", "XZY"); layer_element.addExtension<Acts::ActsExtension>(layerExtension); for (xml_coll_t ri(x_layer, _U(ring)); ri; ++ri) { xml_comp_t x_ring = ri; double r = x_ring.r(); double phi0 = x_ring.phi0(0); double zstart = x_ring.zstart(); double dz = x_ring.dz(0); int nmodules = x_ring.nmodules(); string m_nam = x_ring.moduleStr(); Volume m_vol = modules[m_nam]; double iphi = 2 * M_PI / nmodules; double phi = phi0; Placements& sensVols = sensitives[m_nam]; for (int k = 0; k < nmodules; ++k) { string m_base = _toString(l_id, "layer%d") + _toString(mod_num, "_module%d"); double x = -r * std::cos(phi); double y = -r * std::sin(phi); if (!reflect) { DetElement module(sdet, m_base + "_pos", det_id); pv = layer_vol.placeVolume( m_vol, Transform3D(RotationZYX(0, -M_PI / 2 - phi, -M_PI / 2), Position(x, y, zstart + dz))); pv.addPhysVolID("barrel", 1).addPhysVolID("layer", l_id).addPhysVolID("module", mod_num); module.setPlacement(pv); for (size_t ic = 0; ic < sensVols.size(); ++ic) { PlacedVolume sens_pv = sensVols[ic]; DetElement comp_elt(module, sens_pv.volume().name(), mod_num); comp_elt.setPlacement(sens_pv); Acts::ActsExtension* moduleExtension = new Acts::ActsExtension(); comp_elt.addExtension<Acts::ActsExtension>(moduleExtension); } } else { pv = layer_vol.placeVolume( m_vol, Transform3D(RotationZYX(0, -M_PI / 2 - phi, -M_PI / 2), Position(x, y, -zstart - dz))); pv.addPhysVolID("barrel", 2).addPhysVolID("layer", l_id).addPhysVolID("module", mod_num); DetElement r_module(sdet, m_base + "_neg", det_id); r_module.setPlacement(pv); for (size_t ic = 0; ic < sensVols.size(); ++ic) { PlacedVolume sens_pv = sensVols[ic]; DetElement comp_elt(r_module, sens_pv.volume().name(), mod_num); comp_elt.setPlacement(sens_pv); Acts::ActsExtension* moduleExtension = new Acts::ActsExtension(); comp_elt.addExtension<Acts::ActsExtension>(moduleExtension); } } dz = -dz; phi += iphi; ++mod_num; } } } pv = motherVol.placeVolume(assembly,Position(0,0,(reflect?-1.0e-9:1.0e-9)) ); pv.addPhysVolID("system", det_id); sdet.setPlacement(pv); return sdet; } // clang-format off DECLARE_DETELEMENT(refdet_TrapEndcapTracker, create_detector) DECLARE_DETELEMENT(refdet_GEMTrackerEndcap, create_detector)