File indexing completed on 2026-09-13 08:27:12
0001
0002
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 #include <XML/Utilities.h>
0015
0016
0017
0018
0019
0020 using std::make_tuple;
0021 using std::map;
0022 using std::string;
0023 using std::tuple;
0024 using std::vector;
0025 using namespace dd4hep;
0026
0027 static tuple<Volume, Position> build_module(Detector& desc, xml_coll_t& plm,
0028 SensitiveDetector& sens);
0029 static tuple<int, int> add_individuals(
0030 std::function<tuple<Volume, Position>(Detector&, xml_coll_t&, SensitiveDetector&)> build_module,
0031 Detector& desc, Assembly& env, xml_coll_t& plm, SensitiveDetector& sens, int sid);
0032
0033 static Ref_t createDetector(Detector& desc, xml_h e, SensitiveDetector sens) {
0034 xml_det_t x_det = e;
0035 string detName = x_det.nameStr();
0036 int detID = x_det.id();
0037 DetElement det(detName, detID);
0038 sens.setType("calorimeter");
0039
0040
0041 dd4hep::xml::setDetectorTypeFlag(x_det, det);
0042
0043
0044 Assembly detVol(detName);
0045
0046 xml_dim_t pos = x_det.position();
0047 xml_dim_t rot = x_det.rotation();
0048
0049
0050 xml_comp_t plm = x_det.child(_Unicode(placements));
0051 map<int, int> sectorModuleNumbers;
0052 auto addModuleNumbers = [§orModuleNumbers](int sector, int nmod) {
0053 auto it = sectorModuleNumbers.find(sector);
0054 if (it != sectorModuleNumbers.end()) {
0055 it->second += nmod;
0056 } else {
0057 sectorModuleNumbers[sector] = nmod;
0058 }
0059 };
0060
0061 int sector_id = 1;
0062
0063 for (xml_coll_t mod(plm, _Unicode(individuals)); mod; ++mod) {
0064 auto [sector, nmod] = add_individuals(build_module, desc, detVol, mod, sens, sector_id++);
0065 addModuleNumbers(sector, nmod);
0066 }
0067
0068
0069 Volume motherVol = desc.pickMotherVolume(det);
0070 Transform3D tr(RotationZYX(rot.z(), rot.y(), rot.x()), Position(pos.x(), pos.y(), pos.z()));
0071 PlacedVolume detPV = motherVol.placeVolume(detVol, tr);
0072 detPV.addPhysVolID("system", detID);
0073 det.setPlacement(detPV);
0074 return det;
0075 }
0076
0077
0078 static tuple<Volume, Position> build_module(Detector& desc, xml::Collection_t& plm,
0079 SensitiveDetector& sens) {
0080 auto mod = plm.child(_Unicode(module));
0081 auto sx = mod.attr<double>(_Unicode(sizex));
0082 auto sy = mod.attr<double>(_Unicode(sizey));
0083 auto sz = mod.attr<double>(_Unicode(sizez));
0084 Box modShape(sx / 2., sy / 2., sz / 2.);
0085 auto modMat = desc.material(mod.attr<string>(_Unicode(material)));
0086 Volume modVol("module_vol", modShape, modMat);
0087 modVol.setSensitiveDetector(sens);
0088 modVol.setVisAttributes(desc.visAttributes(mod.attr<string>(_Unicode(vis))));
0089
0090
0091 if (!plm.hasChild(_Unicode(wrapper))) {
0092 return make_tuple(modVol, Position{sx, sy, sz});
0093
0094 } else {
0095 auto wrp = plm.child(_Unicode(wrapper));
0096 auto thickness = wrp.attr<double>(_Unicode(thickness));
0097 if (thickness < 1e-12 * mm) {
0098 return make_tuple(modVol, Position{sx, sy, sz});
0099 }
0100 auto wrpMat = desc.material(wrp.attr<string>(_Unicode(material)));
0101 Box wrpShape((sx + thickness) / 2., (sy + thickness) / 2., sz / 2.);
0102 Volume wrpVol("wrapper_vol", wrpShape, wrpMat);
0103 wrpVol.placeVolume(modVol, Position(0., 0., 0.));
0104 wrpVol.setVisAttributes(desc.visAttributes(wrp.attr<string>(_Unicode(vis))));
0105 return make_tuple(wrpVol, Position{sx + thickness, sy + thickness, sz});
0106 }
0107 }
0108
0109
0110 static tuple<int, int> add_individuals(
0111 std::function<tuple<Volume, Position>(Detector&, xml_coll_t&, SensitiveDetector&)> build_module,
0112 Detector& desc, Assembly& env, xml_coll_t& plm, SensitiveDetector& sens, int sid) {
0113 auto [modVol, modSize] = build_module(desc, plm, sens);
0114 int sector_id = dd4hep::getAttrOrDefault<int>(plm, _Unicode(sector), sid);
0115 int nmodules = 0;
0116 for (xml_coll_t pl(plm, _Unicode(placement)); pl; ++pl) {
0117 Position pos(dd4hep::getAttrOrDefault<double>(pl, _Unicode(x), 0.),
0118 dd4hep::getAttrOrDefault<double>(pl, _Unicode(y), 0.),
0119 dd4hep::getAttrOrDefault<double>(pl, _Unicode(z), 0.));
0120 Position rot(dd4hep::getAttrOrDefault<double>(pl, _Unicode(rotx), 0.),
0121 dd4hep::getAttrOrDefault<double>(pl, _Unicode(roty), 0.),
0122 dd4hep::getAttrOrDefault<double>(pl, _Unicode(rotz), 0.));
0123 auto mid = pl.attr<int>(_Unicode(id));
0124 Transform3D tr =
0125 Translation3D(pos.x(), pos.y(), pos.z()) * RotationZYX(rot.z(), rot.y(), rot.x());
0126 auto modPV = env.placeVolume(modVol, tr);
0127 modPV.addPhysVolID("sector", sector_id).addPhysVolID("module", mid);
0128 nmodules++;
0129 }
0130
0131 return {sector_id, nmodules};
0132 }
0133
0134 DECLARE_DETELEMENT(B0_ECAL, createDetector)