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 Sakib Rahman, Whitney Armstrong
0003 
0004 #include <vector>
0005 #include <functional>
0006 
0007 #include "DD4hep/DetFactoryHelper.h"
0008 #include "DD4hep/OpticalSurfaces.h"
0009 #include "DD4hep/Printout.h"
0010 #include "DDRec/DetectorData.h"
0011 #include "DDRec/Surface.h"
0012 #include "Math/Point2D.h"
0013 #include <XML/Helper.h>
0014 
0015 //////////////////////////////////////////////////
0016 // Far Forward B0 Electromagnetic Calorimeter
0017 //////////////////////////////////////////////////
0018 
0019 using std::make_tuple;
0020 using std::map;
0021 using std::string;
0022 using std::tuple;
0023 using std::vector;
0024 using namespace dd4hep;
0025 
0026 static tuple<Volume, Position> build_module(Detector& desc, xml_coll_t& plm,
0027                                             SensitiveDetector& sens);
0028 static tuple<int, int> add_individuals(
0029     std::function<tuple<Volume, Position>(Detector&, xml_coll_t&, SensitiveDetector&)> build_module,
0030     Detector& desc, Assembly& env, xml_coll_t& plm, SensitiveDetector& sens, int sid);
0031 
0032 static Ref_t createDetector(Detector& desc, xml_h e, SensitiveDetector sens) {
0033   xml_det_t x_det = e;
0034   string detName  = x_det.nameStr();
0035   int detID       = x_det.id();
0036   DetElement det(detName, detID);
0037   sens.setType("calorimeter");
0038 
0039   // assembly
0040   Assembly detVol(detName);
0041 
0042   xml_dim_t pos = x_det.position();
0043   xml_dim_t rot = x_det.rotation();
0044 
0045   // module placement
0046   xml_comp_t plm = x_det.child(_Unicode(placements));
0047   map<int, int> sectorModuleNumbers;
0048   auto addModuleNumbers = [&sectorModuleNumbers](int sector, int nmod) {
0049     auto it = sectorModuleNumbers.find(sector);
0050     if (it != sectorModuleNumbers.end()) {
0051       it->second += nmod;
0052     } else {
0053       sectorModuleNumbers[sector] = nmod;
0054     }
0055   };
0056 
0057   int sector_id = 1;
0058 
0059   for (xml_coll_t mod(plm, _Unicode(individuals)); mod; ++mod) {
0060     auto [sector, nmod] = add_individuals(build_module, desc, detVol, mod, sens, sector_id++);
0061     addModuleNumbers(sector, nmod);
0062   }
0063 
0064   // position and rotation of parent volume
0065   Volume motherVol = desc.pickMotherVolume(det);
0066   Transform3D tr(RotationZYX(rot.z(), rot.y(), rot.x()), Position(pos.x(), pos.y(), pos.z()));
0067   PlacedVolume detPV = motherVol.placeVolume(detVol, tr);
0068   detPV.addPhysVolID("system", detID);
0069   det.setPlacement(detPV);
0070   return det;
0071 }
0072 
0073 // helper function to build module with or w/o wrapper
0074 static tuple<Volume, Position> build_module(Detector& desc, xml::Collection_t& plm,
0075                                             SensitiveDetector& sens) {
0076   auto mod = plm.child(_Unicode(module));
0077   auto sx  = mod.attr<double>(_Unicode(sizex));
0078   auto sy  = mod.attr<double>(_Unicode(sizey));
0079   auto sz  = mod.attr<double>(_Unicode(sizez));
0080   Box modShape(sx / 2., sy / 2., sz / 2.);
0081   auto modMat = desc.material(mod.attr<string>(_Unicode(material)));
0082   Volume modVol("module_vol", modShape, modMat);
0083   modVol.setSensitiveDetector(sens);
0084   modVol.setVisAttributes(desc.visAttributes(mod.attr<string>(_Unicode(vis))));
0085 
0086   // no wrapper
0087   if (!plm.hasChild(_Unicode(wrapper))) {
0088     return make_tuple(modVol, Position{sx, sy, sz});
0089     // build wrapper
0090   } else {
0091     auto wrp       = plm.child(_Unicode(wrapper));
0092     auto thickness = wrp.attr<double>(_Unicode(thickness));
0093     if (thickness < 1e-12 * mm) {
0094       return make_tuple(modVol, Position{sx, sy, sz});
0095     }
0096     auto wrpMat = desc.material(wrp.attr<string>(_Unicode(material)));
0097     Box wrpShape((sx + thickness) / 2., (sy + thickness) / 2., sz / 2.);
0098     Volume wrpVol("wrapper_vol", wrpShape, wrpMat);
0099     wrpVol.placeVolume(modVol, Position(0., 0., 0.));
0100     wrpVol.setVisAttributes(desc.visAttributes(wrp.attr<string>(_Unicode(vis))));
0101     return make_tuple(wrpVol, Position{sx + thickness, sy + thickness, sz});
0102   }
0103 }
0104 
0105 // place modules, id must be provided
0106 static tuple<int, int> add_individuals(
0107     std::function<tuple<Volume, Position>(Detector&, xml_coll_t&, SensitiveDetector&)> build_module,
0108     Detector& desc, Assembly& env, xml_coll_t& plm, SensitiveDetector& sens, int sid) {
0109   auto [modVol, modSize] = build_module(desc, plm, sens);
0110   int sector_id          = dd4hep::getAttrOrDefault<int>(plm, _Unicode(sector), sid);
0111   int nmodules           = 0;
0112   for (xml_coll_t pl(plm, _Unicode(placement)); pl; ++pl) {
0113     Position pos(dd4hep::getAttrOrDefault<double>(pl, _Unicode(x), 0.),
0114                  dd4hep::getAttrOrDefault<double>(pl, _Unicode(y), 0.),
0115                  dd4hep::getAttrOrDefault<double>(pl, _Unicode(z), 0.));
0116     Position rot(dd4hep::getAttrOrDefault<double>(pl, _Unicode(rotx), 0.),
0117                  dd4hep::getAttrOrDefault<double>(pl, _Unicode(roty), 0.),
0118                  dd4hep::getAttrOrDefault<double>(pl, _Unicode(rotz), 0.));
0119     auto mid = pl.attr<int>(_Unicode(id));
0120     Transform3D tr =
0121         Translation3D(pos.x(), pos.y(), pos.z()) * RotationZYX(rot.z(), rot.y(), rot.x());
0122     auto modPV = env.placeVolume(modVol, tr);
0123     modPV.addPhysVolID("sector", sector_id).addPhysVolID("module", mid);
0124     nmodules++;
0125   }
0126 
0127   return {sector_id, nmodules};
0128 }
0129 
0130 DECLARE_DETELEMENT(B0_ECAL, createDetector)