File indexing completed on 2024-09-27 07:02:36
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <array>
0010 #include <map>
0011 #include "DD4hep/DetFactoryHelper.h"
0012 #include "DD4hep/Printout.h"
0013 #include "DD4hep/Shapes.h"
0014 #include "DDRec/Surface.h"
0015 #include "DDRec/DetectorData.h"
0016 #include "XML/Utilities.h"
0017 #include "XML/Layering.h"
0018
0019 #if defined(USE_ACTSDD4HEP)
0020 #include "ActsDD4hep/ActsExtension.hpp"
0021 #include "ActsDD4hep/ConvertMaterial.hpp"
0022 #else
0023 #include "Acts/Plugins/DD4hep/ActsExtension.hpp"
0024 #include "Acts/Plugins/DD4hep/ConvertDD4hepMaterial.hpp"
0025 #endif
0026
0027 using namespace std;
0028 using namespace dd4hep;
0029 using namespace dd4hep::rec;
0030 using namespace dd4hep::detail;
0031
0032
0033
0034
0035
0036
0037 static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens)
0038 {
0039 typedef vector<PlacedVolume> Placements;
0040 xml_det_t x_det = e;
0041 Material vacuum = description.vacuum();
0042 int det_id = x_det.id();
0043 string det_name = x_det.nameStr();
0044 bool reflect = x_det.reflect(false);
0045 DetElement sdet(det_name, det_id);
0046 Assembly assembly(det_name);
0047
0048 Material air = description.material("Air");
0049
0050 Volume motherVol = description.pickMotherVolume(sdet);
0051 int m_id = 0, c_id = 0, n_sensor = 0;
0052 map<string, Volume> modules;
0053 map<string, Placements> sensitives;
0054 map<string, std::vector<VolPlane>> volplane_surfaces;
0055 map<string, std::array<double, 2>> module_thicknesses;
0056 PlacedVolume pv;
0057
0058
0059
0060 {
0061 Acts::ActsExtension* detWorldExt = new Acts::ActsExtension();
0062 detWorldExt->addType("endcap", "detector");
0063
0064
0065
0066
0067
0068 for (xml_coll_t bmat(x_det, _Unicode(boundary_material)); bmat; ++bmat) {
0069 xml_comp_t x_boundary_material = bmat;
0070 Acts::xmlToProtoSurfaceMaterial(x_boundary_material, *detWorldExt, "boundary_material");
0071 }
0072 sdet.addExtension<Acts::ActsExtension>(detWorldExt);
0073 }
0074
0075 assembly.setVisAttributes(description.invisible());
0076 sens.setType("tracker");
0077
0078 for (xml_coll_t su(x_det, _U(support)); su; ++su) {
0079 xml_comp_t x_support = su;
0080 double support_thickness = getAttrOrDefault(x_support, _U(thickness), 2.0 * mm);
0081 double support_length = getAttrOrDefault(x_support, _U(length), 2.0 * mm);
0082 double support_rmin = getAttrOrDefault(x_support, _U(rmin), 2.0 * mm);
0083 double support_zstart = getAttrOrDefault(x_support, _U(zstart), 2.0 * mm);
0084 std::string support_name = getAttrOrDefault<std::string>(x_support, _Unicode(name), "support_tube");
0085 std::string support_vis = getAttrOrDefault<std::string>(x_support, _Unicode(vis), "AnlRed");
0086 xml_dim_t pos (x_support.child(_U(position), false));
0087 xml_dim_t rot (x_support.child(_U(rotation), false));
0088 Solid support_solid;
0089 if(x_support.hasChild("shape")){
0090 xml_comp_t shape(x_support.child(_U(shape)));
0091 string shape_type = shape.typeStr();
0092 support_solid = xml::createShape(description, shape_type, shape);
0093 } else {
0094 support_solid = Tube(support_rmin, support_rmin + support_thickness, support_length / 2);
0095 }
0096 Transform3D tr = Transform3D(Rotation3D(),Position(0,0,(reflect?-1.0:1.0) * (support_zstart + support_length / 2)));
0097 if ( pos.ptr() && rot.ptr() ) {
0098 Rotation3D rot3D(RotationZYX(rot.z(0),rot.y(0),rot.x(0)));
0099 Position pos3D(pos.x(0),pos.y(0),pos.z(0));
0100 tr = Transform3D(rot3D, pos3D);
0101 }
0102 else if ( pos.ptr() ) {
0103 tr = Transform3D(Rotation3D(),Position(pos.x(0),pos.y(0),pos.z(0)));
0104 }
0105 else if ( rot.ptr() ) {
0106 Rotation3D rot3D(RotationZYX(rot.z(0),rot.y(0),rot.x(0)));
0107 tr = Transform3D(rot3D,Position());
0108 }
0109 Material support_mat = description.material(x_support.materialStr());
0110 Volume support_vol(support_name, support_solid, support_mat);
0111 support_vol.setVisAttributes(description.visAttributes(support_vis));
0112 pv = assembly.placeVolume(support_vol, tr);
0113
0114 }
0115
0116 for (xml_coll_t mi(x_det, _U(module)); mi; ++mi, ++m_id) {
0117 xml_comp_t x_mod = mi;
0118 string m_nam = x_mod.nameStr();
0119 xml_comp_t trd = x_mod.trd();
0120
0121 double posY;
0122 double x1 = trd.x1();
0123 double x2 = trd.x2();
0124 double z = trd.z();
0125 double total_thickness = 0.;
0126 xml_coll_t ci(x_mod, _U(module_component));
0127 for (ci.reset(), total_thickness = 0.0; ci; ++ci)
0128 total_thickness += xml_comp_t(ci).thickness();
0129
0130 double thickness_so_far = 0.0;
0131 double thickness_sum = -total_thickness / 2.0;
0132 double y1 = total_thickness / 2;
0133 double y2 = total_thickness / 2;
0134 Trapezoid m_solid(x1, x2, y1, y2, z);
0135 Volume m_volume(m_nam, m_solid, vacuum);
0136 m_volume.setVisAttributes(description.visAttributes(x_mod.visStr()));
0137
0138 Solid frame_s;
0139 if(x_mod.hasChild("frame")){
0140
0141 xml_comp_t m_frame = x_mod.child(_U(frame));
0142 xml_comp_t f_pos = m_frame.child(_U(position));
0143 xml_comp_t frame_trd = m_frame.trd();
0144 double frame_thickness = getAttrOrDefault(m_frame, _U(thickness), total_thickness);
0145 double frame_x1 = frame_trd.x1();
0146 double frame_x2 = frame_trd.x2();
0147 double frame_z = frame_trd.z();
0148
0149 Trapezoid f_solid1(x1, x2,frame_thickness / 2.0, frame_thickness / 2.0, z);
0150 Trapezoid f_solid(frame_x1, frame_x2, frame_thickness / 2.0, frame_thickness / 2.0, frame_z) ;
0151 SubtractionSolid frame_shape(f_solid1, f_solid);
0152 frame_s = frame_shape;
0153
0154 Material f_mat = description.material(m_frame.materialStr());
0155 Volume f_vol(m_nam + "_frame", frame_shape, f_mat);
0156 f_vol.setVisAttributes(description.visAttributes(m_frame.visStr()));
0157
0158
0159 pv = m_volume.placeVolume(f_vol, Position(f_pos.x(), f_pos.y(), f_pos.z()));
0160 }
0161
0162 for (ci.reset(), n_sensor = 1, c_id = 0, posY = -y1; ci; ++ci, ++c_id) {
0163 xml_comp_t c = ci;
0164 double c_thick = c.thickness();
0165 auto comp_x1 = getAttrOrDefault(c, _Unicode(x1), x1);
0166 auto comp_x2 = getAttrOrDefault(c, _Unicode(x2), x2);
0167 auto comp_height = getAttrOrDefault(c, _Unicode(height), z);
0168
0169 Material c_mat = description.material(c.materialStr());
0170 string c_name = _toString(c_id, "component%d");
0171
0172 Trapezoid comp_s1(comp_x1, comp_x2, c_thick / 2e0, c_thick / 2e0, comp_height);
0173 Solid comp_shape = comp_s1;
0174 if(frame_s.isValid()) {
0175 comp_shape = SubtractionSolid( comp_s1, frame_s);
0176 }
0177 Volume c_vol(c_name, comp_shape, c_mat);
0178
0179 c_vol.setVisAttributes(description.visAttributes(c.visStr()));
0180 pv = m_volume.placeVolume(c_vol, Position(0, posY + c_thick / 2, 0));
0181 if (c.isSensitive()) {
0182 module_thicknesses[m_nam] = {thickness_so_far + c_thick/2.0, total_thickness-thickness_so_far - c_thick/2.0};
0183
0184 sdet.check(n_sensor > 2, "SiTrackerEndcap2::fromCompact: " + c_name + " Max of 2 modules allowed!");
0185 pv.addPhysVolID("sensor", n_sensor);
0186 sens.setType("tracker");
0187 c_vol.setSensitiveDetector(sens);
0188 sensitives[m_nam].push_back(pv);
0189 ++n_sensor;
0190
0191 Vector3D u(0., 0., -1.);
0192 Vector3D v(-1., 0., 0.);
0193 Vector3D n(0., 1., 0.);
0194
0195
0196
0197
0198 double inner_thickness = module_thicknesses[m_nam][0];
0199 double outer_thickness = module_thicknesses[m_nam][1];
0200
0201 SurfaceType type(SurfaceType::Sensitive);
0202
0203
0204
0205
0206 VolPlane surf(c_vol, type, inner_thickness, outer_thickness, u, v, n);
0207 volplane_surfaces[m_nam].push_back(surf);
0208
0209
0210 }
0211 posY += c_thick;
0212 thickness_sum += c_thick;
0213 thickness_so_far += c_thick;
0214 }
0215 modules[m_nam] = m_volume;
0216 }
0217
0218 for (xml_coll_t li(x_det, _U(layer)); li; ++li) {
0219 xml_comp_t x_layer(li);
0220 int l_id = x_layer.id();
0221 int mod_num = 1;
0222
0223 xml_comp_t l_env = x_layer.child(_U(envelope));
0224 string layer_name = det_name + std::string("_layer") + std::to_string(l_id);
0225
0226 std::string layer_vis = l_env.attr<std::string>(_Unicode(vis));
0227 double layer_rmin = l_env.attr<double>(_Unicode(rmin));
0228 double layer_rmax = l_env.attr<double>(_Unicode(rmax));
0229 double layer_length = l_env.attr<double>(_Unicode(length));
0230 double layer_zstart = l_env.attr<double>(_Unicode(zstart));
0231 double layer_center_z = layer_zstart + layer_length/2.0;
0232
0233
0234
0235
0236
0237 Tube layer_tub(layer_rmin, layer_rmax, layer_length / 2);
0238 Volume layer_vol(layer_name, layer_tub, air);
0239 layer_vol.setVisAttributes(description.visAttributes(layer_vis));
0240
0241 PlacedVolume layer_pv;
0242 if (reflect) {
0243 layer_pv =
0244 assembly.placeVolume(layer_vol, Transform3D(RotationZYX(0.0, -M_PI, 0.0), Position(0, 0, -layer_center_z)));
0245 layer_pv.addPhysVolID("layer", l_id);
0246 layer_name += "_N";
0247 } else {
0248 layer_pv = assembly.placeVolume(layer_vol, Position(0, 0, layer_center_z));
0249 layer_pv.addPhysVolID("layer", l_id);
0250 layer_name += "_P";
0251 }
0252 DetElement layer_element(sdet, layer_name, l_id);
0253 layer_element.setPlacement(layer_pv);
0254
0255 Acts::ActsExtension* layerExtension = new Acts::ActsExtension();
0256 layerExtension->addType("sensitive disk", "layer");
0257
0258
0259
0260 for (xml_coll_t lmat(x_layer, _Unicode(layer_material)); lmat; ++lmat) {
0261 xml_comp_t x_layer_material = lmat;
0262 xmlToProtoSurfaceMaterial(x_layer_material, *layerExtension, "layer_material");
0263 }
0264 layer_element.addExtension<Acts::ActsExtension>(layerExtension);
0265
0266 for (xml_coll_t ri(x_layer, _U(ring)); ri; ++ri) {
0267 xml_comp_t x_ring = ri;
0268 double r = x_ring.r();
0269 double phi0 = x_ring.phi0(0);
0270 double zstart = x_ring.zstart();
0271 double dz = x_ring.dz(0);
0272 int nmodules = x_ring.nmodules();
0273 string m_nam = x_ring.moduleStr();
0274 Volume m_vol = modules[m_nam];
0275 double iphi = 2 * M_PI / nmodules;
0276 double phi = phi0;
0277 Placements& sensVols = sensitives[m_nam];
0278
0279 for (int k = 0; k < nmodules; ++k) {
0280 string m_base = _toString(l_id, "layer%d") + _toString(mod_num, "_module%d");
0281 double x = -r * std::cos(phi);
0282 double y = -r * std::sin(phi);
0283
0284 if (!reflect) {
0285 DetElement module(layer_element, m_base + "_pos", det_id);
0286 pv = layer_vol.placeVolume(
0287 m_vol, Transform3D(RotationZYX(0, -M_PI / 2 - phi, -M_PI / 2), Position(x, y, zstart + dz)));
0288 pv.addPhysVolID("module", mod_num);
0289 module.setPlacement(pv);
0290 for (size_t ic = 0; ic < sensVols.size(); ++ic) {
0291 PlacedVolume sens_pv = sensVols[ic];
0292 DetElement comp_elt(module, sens_pv.volume().name(), mod_num);
0293 comp_elt.setPlacement(sens_pv);
0294
0295 Acts::ActsExtension* moduleExtension = new Acts::ActsExtension("XZY");
0296 comp_elt.addExtension<Acts::ActsExtension>(moduleExtension);
0297 volSurfaceList(comp_elt)->push_back(volplane_surfaces[m_nam][ic]);
0298 }
0299 } else {
0300 pv = layer_vol.placeVolume(
0301 m_vol, Transform3D(RotationZYX(0, -M_PI / 2 - phi, -M_PI / 2), Position(x, y, -zstart - dz)));
0302 pv.addPhysVolID("module", mod_num);
0303 DetElement r_module(layer_element, m_base + "_neg", det_id);
0304 r_module.setPlacement(pv);
0305 for (size_t ic = 0; ic < sensVols.size(); ++ic) {
0306 PlacedVolume sens_pv = sensVols[ic];
0307 DetElement comp_elt(r_module, sens_pv.volume().name(), mod_num);
0308 comp_elt.setPlacement(sens_pv);
0309
0310 Acts::ActsExtension* moduleExtension = new Acts::ActsExtension("XZY");
0311 comp_elt.addExtension<Acts::ActsExtension>(moduleExtension);
0312 volSurfaceList(comp_elt)->push_back(volplane_surfaces[m_nam][ic]);
0313 }
0314 }
0315 dz = -dz;
0316 phi += iphi;
0317 ++mod_num;
0318 }
0319 }
0320 }
0321 pv = motherVol.placeVolume(assembly,Position(0,0,(reflect?-1.0e-9:1.0e-9)) );
0322 pv.addPhysVolID("system", det_id);
0323 sdet.setPlacement(pv);
0324 return sdet;
0325 }
0326
0327
0328
0329 DECLARE_DETELEMENT(athena_TrapEndcapTracker, create_detector)
0330 DECLARE_DETELEMENT(athena_GEMTrackerEndcap, create_detector)