File indexing completed on 2025-01-18 09:15:52
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
0015
0016
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
0040 Assembly detVol(detName);
0041
0042 xml_dim_t pos = x_det.position();
0043 xml_dim_t rot = x_det.rotation();
0044
0045
0046 xml_comp_t plm = x_det.child(_Unicode(placements));
0047 map<int, int> sectorModuleNumbers;
0048 auto addModuleNumbers = [§orModuleNumbers](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
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
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
0087 if (!plm.hasChild(_Unicode(wrapper))) {
0088 return make_tuple(modVol, Position{sx, sy, sz});
0089
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
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)