Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:15:52

0001 // SPDX-License-Identifier: LGPL-3.0-or-later
0002 // Copyright (C) 2022 Whitney Armstrong
0003 
0004 #include "DD4hep/DetFactoryHelper.h"
0005 #include "DD4hep/Printout.h"
0006 #include "DD4hep/Shapes.h"
0007 #include "DDRec/DetectorData.h"
0008 #include "DDRec/Surface.h"
0009 #include "XML/Layering.h"
0010 #include "XML/Utilities.h"
0011 #include <array>
0012 #include <map>
0013 #include "DD4hepDetectorHelper.h"
0014 
0015 using namespace std;
0016 using namespace dd4hep;
0017 using namespace dd4hep::rec;
0018 using namespace dd4hep::detail;
0019 
0020 /*! B0 Tracker.
0021  *
0022  * @author Whitney Armstrong
0023  *
0024  */
0025 static Ref_t create_B0Tracker(Detector& description, xml_h e, SensitiveDetector sens) {
0026   typedef vector<PlacedVolume> Placements;
0027   xml_det_t x_det = e;
0028   Material vacuum = description.vacuum();
0029   int det_id      = x_det.id();
0030   string det_name = x_det.nameStr();
0031   DetElement sdet(det_name, det_id);
0032   Assembly assembly(det_name);
0033   xml::Component pos = x_det.position();
0034   xml::Component rot = x_det.rotation();
0035 
0036   Volume motherVol = description.pickMotherVolume(sdet);
0037   int m_id = 0, c_id = 0, n_sensor = 0;
0038   PlacedVolume pv;
0039 
0040   map<string, Volume> modules;
0041   map<string, Placements> sensitives;
0042   map<string, std::vector<VolPlane>> volplane_surfaces;
0043   map<string, std::array<double, 2>> module_thicknesses;
0044 
0045   // Set detector type flag
0046   dd4hep::xml::setDetectorTypeFlag(x_det, sdet);
0047   auto& params = DD4hepDetectorHelper::ensureExtension<dd4hep::rec::VariantParameters>(sdet);
0048 
0049   // Add the volume boundary material if configured
0050   for (xml_coll_t bmat(x_det, _Unicode(boundary_material)); bmat; ++bmat) {
0051     xml_comp_t x_boundary_material = bmat;
0052     DD4hepDetectorHelper::xmlToProtoSurfaceMaterial(x_boundary_material, params,
0053                                                     "boundary_material");
0054   }
0055 
0056   assembly.setVisAttributes(description.invisible());
0057   sens.setType("tracker");
0058 
0059   for (xml_coll_t mi(x_det, _U(module)); mi; ++mi, ++m_id) {
0060     xml_comp_t x_mod = mi;
0061     string m_nam     = x_mod.nameStr();
0062     xml_comp_t trd   = x_mod.trd();
0063 
0064     double posY;
0065     double x1 = trd.x1();
0066     double x2 = trd.x2();
0067     double z  = trd.z();
0068     double y1, y2, total_thickness = 0.;
0069     xml_coll_t ci(x_mod, _U(module_component));
0070     for (ci.reset(), total_thickness = 0.0; ci; ++ci)
0071       total_thickness += xml_comp_t(ci).thickness();
0072 
0073     y1 = y2 = total_thickness / 2;
0074     Trapezoid m_solid(x1, x2, y1, y2, z);
0075     Volume m_volume(m_nam, m_solid, vacuum);
0076     m_volume.setVisAttributes(description.visAttributes(x_mod.visStr()));
0077 
0078     Solid frame_s;
0079     if (x_mod.hasChild(_U(frame))) {
0080       // build frame from trd (assumed to be smaller)
0081       xml_comp_t m_frame     = x_mod.child(_U(frame));
0082       xml_comp_t f_pos       = m_frame.child(_U(position));
0083       xml_comp_t frame_trd   = m_frame.trd();
0084       double frame_thickness = getAttrOrDefault(m_frame, _U(thickness), total_thickness);
0085       double frame_x1        = frame_trd.x1();
0086       double frame_x2        = frame_trd.x2();
0087       double frame_z         = frame_trd.z();
0088       // make the frame match the total thickness if thickness attribute is not given
0089       Trapezoid f_solid1(x1, x2, frame_thickness / 2.0, frame_thickness / 2.0, z);
0090       Trapezoid f_solid(frame_x1, frame_x2, frame_thickness / 2.0, frame_thickness / 2.0, frame_z);
0091       SubtractionSolid frame_shape(f_solid1, f_solid);
0092       frame_s = frame_shape;
0093 
0094       Material f_mat = description.material(m_frame.materialStr());
0095       Volume f_vol(m_nam + "_frame", frame_shape, f_mat);
0096       // f_vol.setVisAttributes(description.visAttributes(m_frame.visStr()));
0097 
0098       // figure out how to best place
0099       pv = m_volume.placeVolume(f_vol, Position(f_pos.x(), f_pos.y(), f_pos.z()));
0100     }
0101 
0102     double thickness_so_far = 0.0;
0103     for (ci.reset(), n_sensor = 1, c_id = 0, posY = -y1; ci; ++ci, ++c_id) {
0104       xml_comp_t c     = ci;
0105       double c_thick   = c.thickness();
0106       auto comp_x1     = getAttrOrDefault(c, _Unicode(x1), x1);
0107       auto comp_x2     = getAttrOrDefault(c, _Unicode(x2), x2);
0108       auto comp_height = getAttrOrDefault(c, _Unicode(height), z);
0109 
0110       Material c_mat = description.material(c.materialStr());
0111       string c_name  = _toString(c_id, "component%d");
0112 
0113       Trapezoid comp_s1(comp_x1, comp_x2, c_thick / 2e0, c_thick / 2e0, comp_height);
0114       Solid comp_shape = comp_s1;
0115       if (frame_s.isValid()) {
0116         comp_shape = SubtractionSolid(comp_s1, frame_s);
0117       }
0118       Volume c_vol(c_name, comp_shape, c_mat);
0119 
0120       c_vol.setVisAttributes(description.visAttributes(c.visStr()));
0121       pv = m_volume.placeVolume(c_vol, Position(0, posY + c_thick / 2, 0));
0122       if (c.isSensitive()) {
0123         // std::cout << " adding sensitive volume" << c_name << "\n";
0124         sdet.check(n_sensor > 2,
0125                    "SiTrackerEndcap2::fromCompact: " + c_name + " Max of 2 modules allowed!");
0126         pv.addPhysVolID("sensor", n_sensor);
0127         c_vol.setSensitiveDetector(sens);
0128         sensitives[m_nam].push_back(pv);
0129         ++n_sensor;
0130 
0131         module_thicknesses[m_nam] = {thickness_so_far + c_thick / 2.0,
0132                                      total_thickness - thickness_so_far - c_thick / 2.0};
0133         // -------- create a measurement plane for the tracking surface attched to the sensitive volume -----
0134         Vector3D u(-1., 0., 0.);
0135         Vector3D v(0., -1., 0.);
0136         Vector3D n(0., 0., 1.);
0137         //    Vector3D o( 0. , 0. , 0. ) ;
0138 
0139         // compute the inner and outer thicknesses that need to be assigned to the tracking surface
0140         // depending on wether the support is above or below the sensor
0141         double inner_thickness = module_thicknesses[m_nam][0];
0142         double outer_thickness = module_thicknesses[m_nam][1];
0143 
0144         SurfaceType type(SurfaceType::Sensitive);
0145 
0146         // if( isStripDetector )
0147         //  type.setProperty( SurfaceType::Measurement1D , true ) ;
0148 
0149         VolPlane surf(c_vol, type, inner_thickness, outer_thickness, u, v, n); //,o ) ;
0150         volplane_surfaces[m_nam].push_back(surf);
0151       }
0152       posY += c_thick;
0153       thickness_so_far += c_thick;
0154     }
0155     modules[m_nam] = m_volume;
0156   }
0157 
0158   for (xml_coll_t li(x_det, _U(layer)); li; ++li) {
0159     xml_comp_t x_layer(li);
0160     int l_id    = x_layer.id();
0161     int mod_num = 1;
0162 
0163     xml_comp_t l_env  = x_layer.child(_U(envelope));
0164     string layer_name = det_name + std::string("_layer") + std::to_string(l_id);
0165 
0166     std::string layer_vis       = l_env.attr<std::string>(_Unicode(vis));
0167     double layer_rmin_tolerance = l_env.attr<double>(_Unicode(rmin_tolerance));
0168     double layer_rmax_tolerance = l_env.attr<double>(_Unicode(rmax_tolerance));
0169     double layer_zmin_tolerance = l_env.attr<double>(_Unicode(zmin_tolerance));
0170     double layer_zmax_tolerance = l_env.attr<double>(_Unicode(zmax_tolerance));
0171     double layer_length         = l_env.attr<double>(_Unicode(length));
0172     double layer_zstart         = l_env.attr<double>(_Unicode(zstart));
0173     double layer_center_z       = layer_zstart + layer_length / 2.0;
0174     // printout(INFO,"ROOTGDMLParse","+++ Read geometry from GDML file file:%s",input.c_str());
0175     // std::cout << "SiTracker Endcap layer " << l_id << " zstart = " << layer_zstart/dd4hep::mm << "mm ( " <<
0176     // layer_length/dd4hep::mm << " mm thick )\n";
0177 
0178     Assembly layer_vol(layer_name);
0179     PlacedVolume layer_pv;
0180     layer_pv = assembly.placeVolume(layer_vol, Position(0, 0, layer_center_z));
0181     layer_pv.addPhysVolID("layer", l_id);
0182     layer_name += "_P";
0183     DetElement layer_element(sdet, layer_name, l_id);
0184     layer_element.setPlacement(layer_pv);
0185 
0186     auto& layerParams =
0187         DD4hepDetectorHelper::ensureExtension<dd4hep::rec::VariantParameters>(layer_element);
0188 
0189     for (xml_coll_t ri(x_layer, _U(ring)); ri; ++ri) {
0190       xml_comp_t x_ring    = ri;
0191       double r             = x_ring.r();
0192       double phi0          = x_ring.phi0(0);
0193       double zstart        = x_ring.zstart();
0194       double dz            = x_ring.dz(0);
0195       int nmodules         = x_ring.nmodules();
0196       string m_nam         = x_ring.moduleStr();
0197       Volume m_vol         = modules[m_nam];
0198       double iphi          = 2 * M_PI / nmodules;
0199       double dphi          = dd4hep::getAttrOrDefault(x_ring, _Unicode(dphi), iphi);
0200       double phi           = phi0;
0201       Placements& sensVols = sensitives[m_nam];
0202 
0203       for (int k = 0; k < nmodules; ++k) {
0204         string m_base = _toString(l_id, "layer%d") + _toString(mod_num, "_module%d");
0205         double x      = -r * std::cos(phi);
0206         double y      = -r * std::sin(phi);
0207 
0208         // if (!reflect) {
0209         DetElement module(layer_element, m_base + "_pos", det_id);
0210         pv = layer_vol.placeVolume(m_vol, Transform3D(RotationZYX(0, -M_PI / 2 - phi, -M_PI / 2),
0211                                                       Position(x, y, zstart + dz)));
0212         pv.addPhysVolID("layer", l_id).addPhysVolID("module", mod_num);
0213         module.setPlacement(pv);
0214         for (size_t ic = 0; ic < sensVols.size(); ++ic) {
0215           PlacedVolume sens_pv = sensVols[ic];
0216           DetElement comp_elt(module, sens_pv.volume().name(), mod_num);
0217           comp_elt.setPlacement(sens_pv);
0218           auto& comp_elt_params =
0219               DD4hepDetectorHelper::ensureExtension<dd4hep::rec::VariantParameters>(comp_elt);
0220           comp_elt_params.set<std::string>("axis_definitions", "XZY");
0221           volSurfaceList(comp_elt)->push_back(volplane_surfaces[m_nam][ic]);
0222         }
0223         dz = -dz;
0224         phi += dphi;
0225         ++mod_num;
0226       }
0227     }
0228     layer_vol->GetShape()->ComputeBBox();
0229     layerParams.set<double>("envelope_r_min", layer_rmin_tolerance / dd4hep::mm);
0230     layerParams.set<double>("envelope_r_max", layer_rmax_tolerance / dd4hep::mm);
0231     layerParams.set<double>("envelope_z_min", layer_zmin_tolerance / dd4hep::mm);
0232     layerParams.set<double>("envelope_z_max", layer_zmax_tolerance / dd4hep::mm);
0233 
0234     for (xml_coll_t lmat(x_layer, _Unicode(layer_material)); lmat; ++lmat) {
0235       xml_comp_t x_layer_material = lmat;
0236       DD4hepDetectorHelper::xmlToProtoSurfaceMaterial(x_layer_material, layerParams,
0237                                                       "layer_material");
0238     }
0239   }
0240   Transform3D posAndRot(RotationZYX(rot.z(), rot.y(), rot.x()),
0241                         Position(pos.x(), pos.y(), pos.z()));
0242   pv = motherVol.placeVolume(assembly, posAndRot);
0243   pv.addPhysVolID("system", det_id);
0244   sdet.setPlacement(pv);
0245   return sdet;
0246 }
0247 
0248 // clang-format off
0249 DECLARE_DETELEMENT(ip6_B0Tracker, create_B0Tracker)