File indexing completed on 2025-10-28 07:58:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include "DD4hep/DetFactoryHelper.h"
0013 #include "DD4hep/Printout.h"
0014 #include "DD4hep/Shapes.h"
0015 #include "DDRec/DetectorData.h"
0016 #include "DDRec/Surface.h"
0017 #include "XML/Layering.h"
0018 #include "XML/Utilities.h"
0019 #include <array>
0020 #include "DD4hepDetectorHelper.h"
0021
0022 using namespace std;
0023 using namespace dd4hep;
0024 using namespace dd4hep::rec;
0025 using namespace dd4hep::detail;
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 static Ref_t create_BarrelTrackerWithFrame(Detector& description, xml_h e, SensitiveDetector sens) {
0048 typedef vector<PlacedVolume> Placements;
0049 xml_det_t x_det = e;
0050 Material air = description.air();
0051 int det_id = x_det.id();
0052 string det_name = x_det.nameStr();
0053 DetElement sdet(det_name, det_id);
0054
0055 map<string, Volume> volumes;
0056 map<string, Placements> sensitives;
0057 map<string, std::vector<VolPlane>> volplane_surfaces;
0058 map<string, std::array<double, 2>> module_thicknesses;
0059
0060 PlacedVolume pv;
0061
0062
0063 dd4hep::xml::setDetectorTypeFlag(x_det, sdet);
0064 auto& params = DD4hepDetectorHelper::ensureExtension<dd4hep::rec::VariantParameters>(sdet);
0065
0066
0067 for (xml_coll_t bmat(x_det, _Unicode(boundary_material)); bmat; ++bmat) {
0068 xml_comp_t x_boundary_material = bmat;
0069 DD4hepDetectorHelper::xmlToProtoSurfaceMaterial(x_boundary_material, params,
0070 "boundary_material");
0071 }
0072
0073
0074
0075
0076 Assembly assembly(det_name);
0077
0078 sens.setType("tracker");
0079
0080
0081 for (xml_coll_t su(x_det, _U(support)); su; ++su) {
0082 xml_comp_t x_support = su;
0083 double support_thickness = getAttrOrDefault(x_support, _U(thickness), 2.0 * mm);
0084 double support_length = getAttrOrDefault(x_support, _U(length), 2.0 * mm);
0085 double support_rmin = getAttrOrDefault(x_support, _U(rmin), 2.0 * mm);
0086 double support_zstart = getAttrOrDefault(x_support, _U(zstart), 2.0 * mm);
0087 std::string support_name =
0088 getAttrOrDefault<std::string>(x_support, _Unicode(name), "support_tube");
0089 std::string support_vis = getAttrOrDefault<std::string>(x_support, _Unicode(vis), "AnlRed");
0090 xml_dim_t pos(x_support.child(_U(position), false));
0091 xml_dim_t rot(x_support.child(_U(rotation), false));
0092 Solid support_solid;
0093 if (x_support.hasChild(_U(shape))) {
0094 xml_comp_t shape(x_support.child(_U(shape)));
0095 string shape_type = shape.typeStr();
0096 support_solid = xml::createShape(description, shape_type, shape);
0097 } else {
0098 support_solid = Tube(support_rmin, support_rmin + support_thickness, support_length / 2);
0099 }
0100 Transform3D tr =
0101 Transform3D(Rotation3D(), Position(0, 0, (support_zstart + support_length / 2)));
0102 if (pos.ptr() && rot.ptr()) {
0103 Rotation3D rot3D(RotationZYX(rot.z(0), rot.y(0), rot.x(0)));
0104 Position pos3D(pos.x(0), pos.y(0), pos.z(0));
0105 tr = Transform3D(rot3D, pos3D);
0106 } else if (pos.ptr()) {
0107 tr = Transform3D(Rotation3D(), Position(pos.x(0), pos.y(0), pos.z(0)));
0108 } else if (rot.ptr()) {
0109 Rotation3D rot3D(RotationZYX(rot.z(0), rot.y(0), rot.x(0)));
0110 tr = Transform3D(rot3D, Position());
0111 }
0112 Material support_mat = description.material(x_support.materialStr());
0113 Volume support_vol(support_name, support_solid, support_mat);
0114 support_vol.setVisAttributes(description.visAttributes(support_vis));
0115 pv = assembly.placeVolume(support_vol, tr);
0116
0117 }
0118
0119
0120 for (xml_coll_t mi(x_det, _U(module)); mi; ++mi) {
0121 xml_comp_t x_mod = mi;
0122 string m_nam = x_mod.nameStr();
0123
0124 if (volumes.find(m_nam) != volumes.end()) {
0125 printout(ERROR, "BarrelTrackerWithFrame",
0126 string((string("Module with named ") + m_nam + string(" already exists."))).c_str());
0127 throw runtime_error("Logics error in building modules.");
0128 }
0129
0130 int ncomponents = 0;
0131 int sensor_number = 1;
0132 double total_thickness = 0;
0133
0134
0135
0136 xml_coll_t ci(x_mod, _U(module_component));
0137 for (ci.reset(), total_thickness = 0.0; ci; ++ci) {
0138 xml_comp_t x_pos = xml_comp_t(ci).position(false);
0139 double mod_z_off = 0;
0140 if (x_pos)
0141 mod_z_off = x_pos.z(0);
0142 total_thickness += xml_comp_t(ci).thickness() + mod_z_off;
0143 }
0144
0145 Assembly m_vol(m_nam);
0146 volumes[m_nam] = m_vol;
0147 m_vol.setVisAttributes(description.visAttributes(x_mod.visStr()));
0148
0149
0150 if (x_mod.hasChild(_U(frame))) {
0151 xml_comp_t m_frame = x_mod.child(_U(frame));
0152
0153 double frame_thickness = m_frame.thickness();
0154 double frame_width = m_frame.width();
0155 double frame_height = getAttrOrDefault<double>(m_frame, _U(height), 5.0 * mm);
0156 double tanth = frame_height / (frame_width / 2.0);
0157 double costh = 1. / sqrt(1 + tanth * tanth);
0158 double frame_height2 = frame_height - frame_thickness - frame_thickness / costh;
0159 double frame_width2 = 2.0 * frame_height2 / tanth;
0160
0161 Trd1 moduleframe_part1(frame_width / 2, 0.001 * mm, m_frame.length() / 2, frame_height / 2);
0162 Trd1 moduleframe_part2(frame_width2 / 2, 0.001 * mm, m_frame.length() / 2 + 0.01 * mm,
0163 frame_height2 / 2);
0164
0165 SubtractionSolid moduleframe(moduleframe_part1, moduleframe_part2,
0166 Position(0.0, frame_thickness, 0.0));
0167 Volume v_moduleframe(m_nam + "_vol", moduleframe,
0168 description.material(m_frame.materialStr()));
0169 v_moduleframe.setVisAttributes(description, m_frame.visStr());
0170 m_vol.placeVolume(v_moduleframe,
0171 Position(0.0, 0.0, frame_height / 2 + total_thickness / 2.0));
0172 }
0173
0174 double thickness_so_far = 0.0;
0175 double thickness_sum = -total_thickness / 2.0;
0176 for (xml_coll_t mci(x_mod, _U(module_component)); mci; ++mci, ++ncomponents) {
0177 xml_comp_t x_comp = mci;
0178 xml_comp_t x_pos = x_comp.position(false);
0179 xml_comp_t x_rot = x_comp.rotation(false);
0180 const string c_nam = _toString(ncomponents, "component%d");
0181 Box c_box(x_comp.width() / 2, x_comp.length() / 2, x_comp.thickness() / 2);
0182 Volume c_vol(c_nam, c_box, description.material(x_comp.materialStr()));
0183
0184
0185 const double zoff = thickness_sum + x_comp.thickness() / 2.0;
0186 if (x_pos && x_rot) {
0187 Position c_pos(x_pos.x(0), x_pos.y(0), x_pos.z(0) + zoff);
0188 RotationZYX c_rot(x_rot.z(0), x_rot.y(0), x_rot.x(0));
0189 pv = m_vol.placeVolume(c_vol, Transform3D(c_rot, c_pos));
0190 } else if (x_rot) {
0191 Position c_pos(0, 0, zoff);
0192 pv = m_vol.placeVolume(c_vol,
0193 Transform3D(RotationZYX(x_rot.z(0), x_rot.y(0), x_rot.x(0)), c_pos));
0194 } else if (x_pos) {
0195 pv = m_vol.placeVolume(c_vol, Position(x_pos.x(0), x_pos.y(0), x_pos.z(0) + zoff));
0196 } else {
0197 pv = m_vol.placeVolume(c_vol, Position(0, 0, zoff));
0198 }
0199 c_vol.setRegion(description, x_comp.regionStr());
0200 c_vol.setLimitSet(description, x_comp.limitsStr());
0201 c_vol.setVisAttributes(description, x_comp.visStr());
0202 if (x_comp.isSensitive()) {
0203 pv.addPhysVolID("sensor", sensor_number++);
0204 c_vol.setSensitiveDetector(sens);
0205 sensitives[m_nam].push_back(pv);
0206 module_thicknesses[m_nam] = {thickness_so_far + x_comp.thickness() / 2.0,
0207 total_thickness - thickness_so_far - x_comp.thickness() / 2.0};
0208
0209
0210 Vector3D u(-1., 0., 0.);
0211 Vector3D v(0., -1., 0.);
0212 Vector3D n(0., 0., 1.);
0213
0214
0215
0216
0217 double inner_thickness = module_thicknesses[m_nam][0];
0218 double outer_thickness = module_thicknesses[m_nam][1];
0219
0220 SurfaceType type(SurfaceType::Sensitive);
0221
0222
0223
0224
0225 VolPlane surf(c_vol, type, inner_thickness, outer_thickness, u, v, n);
0226 volplane_surfaces[m_nam].push_back(surf);
0227
0228
0229 }
0230 thickness_sum += x_comp.thickness();
0231 thickness_so_far += x_comp.thickness();
0232
0233 if (x_pos) {
0234 thickness_sum += x_pos.z(0);
0235 thickness_so_far += x_pos.z(0);
0236 }
0237 }
0238 }
0239
0240
0241 for (xml_coll_t li(x_det, _U(layer)); li; ++li) {
0242 xml_comp_t x_layer = li;
0243 xml_comp_t x_barrel = x_layer.child(_U(barrel_envelope));
0244 xml_comp_t x_layout = x_layer.child(_U(rphi_layout));
0245 xml_comp_t z_layout = x_layer.child(_U(z_layout));
0246 int lay_id = x_layer.id();
0247 string m_nam = x_layer.moduleStr();
0248 string lay_nam = det_name + _toString(x_layer.id(), "_layer%d");
0249 Tube lay_tub(x_barrel.inner_r(), x_barrel.outer_r(), x_barrel.z_length() / 2.0);
0250 Volume lay_vol(lay_nam, lay_tub, air);
0251 Position lay_pos(0, 0, getAttrOrDefault(x_barrel, _U(z0), 0.));
0252 lay_vol.setVisAttributes(description.visAttributes(x_layer.visStr()));
0253
0254 double phi0 = x_layout.phi0();
0255 double phi_tilt = x_layout.phi_tilt();
0256 double rc = x_layout.rc();
0257 int nphi = x_layout.nphi();
0258 double rphi_dr = x_layout.dr();
0259 double phi_incr = (M_PI * 2) / nphi;
0260 double phic = phi0;
0261 double z0 = z_layout.z0();
0262 double nz = z_layout.nz();
0263 double z_dr = z_layout.dr();
0264
0265 Volume module_env = volumes[m_nam];
0266 DetElement lay_elt(sdet, lay_nam, lay_id);
0267 Placements& sensVols = sensitives[m_nam];
0268
0269
0270
0271 auto& layerParams =
0272 DD4hepDetectorHelper::ensureExtension<dd4hep::rec::VariantParameters>(lay_elt);
0273
0274 for (xml_coll_t lmat(x_layer, _Unicode(layer_material)); lmat; ++lmat) {
0275 xml_comp_t x_layer_material = lmat;
0276 DD4hepDetectorHelper::xmlToProtoSurfaceMaterial(x_layer_material, layerParams,
0277 "layer_material");
0278 }
0279
0280
0281
0282
0283 double z_incr = nz > 1 ? (2.0 * z0) / (nz - 1) : 0.0;
0284
0285 double module_z = -z0;
0286 int module = 1;
0287
0288
0289 for (int ii = 0; ii < nphi; ii++) {
0290 double dx = z_dr * std::cos(phic + phi_tilt);
0291 double dy = z_dr * std::sin(phic + phi_tilt);
0292 double x = rc * std::cos(phic);
0293 double y = rc * std::sin(phic);
0294
0295
0296 for (int j = 0; j < nz; j++) {
0297 string module_name = _toString(module, "module%d");
0298 DetElement mod_elt(lay_elt, module_name, module);
0299
0300 Transform3D tr(RotationZYX(0, ((M_PI / 2) - phic - phi_tilt), -M_PI / 2),
0301 Position(x, y, module_z));
0302
0303 pv = lay_vol.placeVolume(module_env, tr);
0304 pv.addPhysVolID("module", module);
0305 mod_elt.setPlacement(pv);
0306 for (size_t ic = 0; ic < sensVols.size(); ++ic) {
0307 PlacedVolume sens_pv = sensVols[ic];
0308 DetElement comp_de(mod_elt, std::string("de_") + sens_pv.volume().name(), module);
0309 comp_de.setPlacement(sens_pv);
0310
0311 auto& comp_de_params =
0312 DD4hepDetectorHelper::ensureExtension<dd4hep::rec::VariantParameters>(comp_de);
0313 comp_de_params.set<string>("axis_definitions", "XYZ");
0314
0315
0316
0317
0318 volSurfaceList(comp_de)->push_back(volplane_surfaces[m_nam][ic]);
0319 }
0320
0321
0322 module++;
0323
0324 x += dx;
0325 y += dy;
0326
0327 dx *= -1;
0328 dy *= -1;
0329
0330 module_z += z_incr;
0331 }
0332 phic += phi_incr;
0333 rc += rphi_dr;
0334 rphi_dr *= -1;
0335 module_z = -z0;
0336 }
0337
0338 pv = assembly.placeVolume(lay_vol, lay_pos);
0339 pv.addPhysVolID("layer", lay_id);
0340 lay_elt.setAttributes(description, lay_vol, x_layer.regionStr(), x_layer.limitsStr(),
0341 x_layer.visStr());
0342 lay_elt.setPlacement(pv);
0343 }
0344 sdet.setAttributes(description, assembly, x_det.regionStr(), x_det.limitsStr(), x_det.visStr());
0345 assembly.setVisAttributes(description.invisible());
0346 pv = description.pickMotherVolume(sdet).placeVolume(assembly);
0347 pv.addPhysVolID("system", det_id);
0348 sdet.setPlacement(pv);
0349 return sdet;
0350 }
0351
0352
0353
0354 DECLARE_DETELEMENT(epic_BarrelTrackerWithFrame, create_BarrelTrackerWithFrame)
0355 DECLARE_DETELEMENT(epic_TrackerBarrel, create_BarrelTrackerWithFrame)
0356 DECLARE_DETELEMENT(epic_VertexBarrel, create_BarrelTrackerWithFrame)
0357 DECLARE_DETELEMENT(epic_InnerMPGDBarrel, create_BarrelTrackerWithFrame)