File indexing completed on 2025-01-18 09:15:59
0001
0002
0003
0004 #include "DD4hep/DetFactoryHelper.h"
0005 #include "XML/Layering.h"
0006 #include "XML/Utilities.h"
0007 #include <map>
0008
0009 using namespace std;
0010 using namespace dd4hep;
0011 using namespace dd4hep::detail;
0012
0013
0014
0015
0016
0017
0018
0019
0020 static Ref_t create_OffMomentumTracker(Detector& description, xml_h e, SensitiveDetector sens) {
0021 typedef vector<PlacedVolume> Placements;
0022 xml_det_t x_det = e;
0023 Material vacuum = description.vacuum();
0024 int det_id = x_det.id();
0025 string det_name = x_det.nameStr();
0026 DetElement sdet(det_name, det_id);
0027 Assembly assembly(det_name);
0028 xml::Component pos = x_det.position();
0029 xml::Component rot = x_det.rotation();
0030
0031
0032
0033 Volume motherVol = description.pickMotherVolume(sdet);
0034 int m_id = 0, c_id = 0, n_sensor = 0;
0035 map<string, Volume> modules;
0036 map<string, Placements> sensitives;
0037 PlacedVolume pv;
0038
0039 assembly.setVisAttributes(description.invisible());
0040 sens.setType("tracker");
0041
0042 for (xml_coll_t su(x_det, _U(support)); su; ++su) {
0043 xml_comp_t x_support = su;
0044 double support_thickness = getAttrOrDefault<double>(x_support, _U(thickness), 2.0 * mm);
0045 double support_length = getAttrOrDefault<double>(x_support, _U(length), 2.0 * mm);
0046 double support_rmin = getAttrOrDefault<double>(x_support, _U(rmin), 2.0 * mm);
0047 double support_zstart = getAttrOrDefault<double>(x_support, _U(zstart), 2.0 * mm);
0048 std::string support_name =
0049 getAttrOrDefault<std::string>(x_support, _Unicode(name), "support_tube");
0050 std::string support_vis = getAttrOrDefault<std::string>(x_support, _Unicode(vis), "AnlRed");
0051 xml_dim_t support_pos(x_support.child(_U(position), false));
0052 xml_dim_t support_rot(x_support.child(_U(rotation), false));
0053 Solid support_solid;
0054 if (x_support.hasChild(_U(shape))) {
0055 xml_comp_t shape(x_support.child(_U(shape)));
0056 string shape_type = shape.typeStr();
0057 support_solid = xml::createShape(description, shape_type, shape);
0058 } else {
0059 support_solid = Tube(support_rmin, support_rmin + support_thickness, support_length / 2);
0060 }
0061 Transform3D tr =
0062 Transform3D(Rotation3D(), Position(0, 0, (support_zstart + support_length / 2)));
0063 if (support_pos.ptr() && support_rot.ptr()) {
0064 Rotation3D rot3D(RotationZYX(support_rot.z(0), support_rot.y(0), support_rot.x(0)));
0065 Position pos3D(support_pos.x(0), support_pos.y(0), support_pos.z(0));
0066 tr = Transform3D(rot3D, pos3D);
0067 } else if (support_pos.ptr()) {
0068 tr =
0069 Transform3D(Rotation3D(), Position(support_pos.x(0), support_pos.y(0), support_pos.z(0)));
0070 } else if (support_rot.ptr()) {
0071 Rotation3D rot3D(RotationZYX(support_rot.z(0), support_rot.y(0), support_rot.x(0)));
0072 tr = Transform3D(rot3D, Position());
0073 }
0074 Material support_mat = description.material(x_support.materialStr());
0075 Volume support_vol(support_name, support_solid, support_mat);
0076 support_vol.setVisAttributes(description.visAttributes(support_vis));
0077 pv = assembly.placeVolume(support_vol, tr);
0078
0079 }
0080
0081 for (xml_coll_t mi(x_det, _U(module)); mi; ++mi, ++m_id) {
0082 xml_comp_t x_mod = mi;
0083 string m_nam = x_mod.nameStr();
0084 xml_comp_t x_box = x_mod.shape();
0085
0086 double x1 = x_box.x();
0087 double y1 = x_box.y();
0088
0089 double total_thickness = 0.;
0090
0091 xml_coll_t ci(x_mod, _U(module_component));
0092 for (ci.reset(), total_thickness = 0.0; ci; ++ci) {
0093 total_thickness += xml_comp_t(ci).thickness();
0094 }
0095
0096 Box m_solid(x1 / 2.0, y1 / 2.0, total_thickness / 2.0);
0097 Volume m_volume(m_nam, m_solid, vacuum);
0098 m_volume.setVisAttributes(description.visAttributes(x_mod.visStr()));
0099
0100
0101 if (x_mod.hasChild(_U(frame))) {
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123 }
0124
0125 double posZ = -total_thickness / 2.0;
0126 for (ci.reset(), n_sensor = 1, c_id = 0, posZ = -total_thickness / 2.0; ci; ++ci, ++c_id) {
0127 xml_comp_t c = ci;
0128 double c_thick = c.thickness();
0129 auto comp_x = getAttrOrDefault(c, _Unicode(x), x1);
0130 auto comp_y = getAttrOrDefault(c, _Unicode(y), y1);
0131
0132 Material c_mat = description.material(c.materialStr());
0133 string c_name = _toString(c_id, "OMD_component%d");
0134
0135 Box comp_s1(comp_x / 2.0, comp_y / 2.0, c_thick / 2e0);
0136 Solid comp_shape = comp_s1;
0137
0138
0139
0140 Volume c_vol(c_name, comp_shape, c_mat);
0141
0142 c_vol.setVisAttributes(description.visAttributes(c.visStr()));
0143 pv = m_volume.placeVolume(c_vol, Position(0, 0, posZ + c_thick / 2.0));
0144 if (c.isSensitive()) {
0145
0146 sdet.check(n_sensor > 2,
0147 "SiTrackerEndcap2::fromCompact: " + c_name + " Max of 2 modules allowed!");
0148 pv.addPhysVolID("slice", n_sensor);
0149 sens.setType("tracker");
0150 c_vol.setSensitiveDetector(sens);
0151 sensitives[m_nam].push_back(pv);
0152 ++n_sensor;
0153 }
0154 posZ += c_thick;
0155 }
0156 modules[m_nam] = m_volume;
0157 }
0158
0159 for (xml_coll_t li(x_det, _U(layer)); li; ++li) {
0160 xml_comp_t x_layer(li);
0161 int l_id = x_layer.id();
0162 int mod_num = 1;
0163
0164 xml_comp_t l_env = x_layer.child(_U(envelope));
0165 string layer_name = det_name + std::string("_layer") + std::to_string(l_id);
0166
0167 std::string layer_vis = l_env.attr<std::string>(_Unicode(vis));
0168
0169
0170 double layer_length = l_env.attr<double>(_Unicode(length));
0171 double layer_zstart = l_env.attr<double>(_Unicode(zstart));
0172 double layer_center_z = layer_zstart + layer_length / 2.0;
0173
0174
0175
0176
0177 Assembly layer_vol(layer_name);
0178
0179
0180
0181 layer_vol.setVisAttributes(description.visAttributes(layer_vis));
0182
0183 PlacedVolume layer_pv;
0184
0185
0186
0187
0188
0189
0190
0191 layer_pv = assembly.placeVolume(layer_vol, Position(0, 0, layer_center_z));
0192 layer_pv.addPhysVolID("layer", l_id);
0193
0194 DetElement layer_element(sdet, layer_name, l_id);
0195 layer_element.setPlacement(layer_pv);
0196
0197 string m_nam = x_layer.moduleStr();
0198 Volume m_vol = modules[m_nam];
0199 Placements& sensVols = sensitives[m_nam];
0200
0201 DetElement module(layer_element, "module_", l_id);
0202 pv = layer_vol.placeVolume(m_vol, Position(0, 0, 0));
0203 pv.addPhysVolID("layer", l_id).addPhysVolID("module", mod_num);
0204 module.setPlacement(pv);
0205 for (size_t ic = 0; ic < sensVols.size(); ++ic) {
0206 PlacedVolume sens_pv = sensVols[ic];
0207 DetElement comp_elt(module, sens_pv.volume().name(), mod_num);
0208 comp_elt.setPlacement(sens_pv);
0209 }
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264 ++mod_num;
0265 }
0266 Transform3D posAndRot(RotationZYX(rot.z(), rot.y(), rot.x()),
0267 Position(pos.x(), pos.y(), pos.z()));
0268 pv = motherVol.placeVolume(assembly, posAndRot);
0269 pv.addPhysVolID("system", det_id);
0270 sdet.setPlacement(pv);
0271 return sdet;
0272 }
0273
0274
0275 DECLARE_DETELEMENT(ip6_OffMomentumTracker, create_OffMomentumTracker)