11 #include "../DetUtils.h"
12 #include "DD4hep/DetFactoryHelper.h"
14 using dd4hep::DetElement;
15 using dd4hep::PlacedVolume;
17 using dd4hep::xml::Component;
18 using dd4hep::xml::Dimension;
22 dd4hep::Detector& lcdd, dd4hep::xml::Handle_t xmlElement,
23 dd4hep::SensitiveDetector sensDet) {
25 dd4hep::xml::DetElement xmlDet =
26 static_cast<dd4hep::xml::DetElement
>(xmlElement);
27 Dimension dimensions(xmlDet.dimensions());
28 double l_overlapMargin = 0.01;
31 dd4hep::xml::Dimension sdTyp =
32 xmlElement.child(_Unicode(sensitive));
33 sensDet.setType(sdTyp.typeStr());
36 std::string detName = xmlDet.nameStr();
37 DetElement worldDetElement(detName, xmlDet.id());
38 DetElement posEcapDetElement(worldDetElement,
"posEndcap", 0);
41 ecapDetExt->
addType(
"endcap",
"detector");
44 dd4hep::Assembly envelopeVolume(
"endcapEnvelope");
45 envelopeVolume.setVisAttributes(lcdd.invisible());
47 Component xDiscs = xmlElement.child(_Unicode(discs));
49 double envelopeThickness = 0.5 * (dimensions.zmax() - dimensions.zmin());
51 l_overlapMargin *= 0.9;
53 unsigned int discCounter = 0;
54 unsigned int compCounter = 0;
56 std::vector<Volume> discVolumeVec;
57 std::vector<DetElement> discDetElementVec;
59 for (dd4hep::xml::Collection_t xDiscColl(xDiscs, _Unicode(discZPls));
60 nullptr != xDiscColl; ++xDiscColl) {
61 Component xDisc =
static_cast<Component
>(xDiscColl);
62 Component xCurrentRings = xDisc.child(_Unicode(rings));
64 double discThickness = 0.5 * (xDisc.zmax() - xDisc.zmin());
65 currentZ = xDisc.z() - dimensions.zmin() - envelopeThickness;
66 if (xCurrentRings.hasChild(
68 dd4hep::Tube discShape(xDisc.rmin() - l_overlapMargin,
69 xDisc.rmax() + l_overlapMargin,
70 discThickness + l_overlapMargin);
72 discVolumeVec.emplace_back(
"disc", discShape, lcdd.air());
73 discDetElementVec.emplace_back(
74 posEcapDetElement,
"disc" +
std::to_string(discCounter), discCounter);
78 detlayer->
addType(
"sensitive disk",
"layer");
79 detlayer->
addType(
"axes",
"definitions",
"XZY");
82 for (dd4hep::xml::Collection_t xRingColl(xCurrentRings, _U(ring));
83 (
nullptr != xRingColl); ++xRingColl) {
84 Component xRing =
static_cast<Component
>(xRingColl);
85 Component xRingModules = xRing.child(_Unicode(modules));
86 Component xModuleOdd = xRingModules.child(_Unicode(moduleOdd));
87 Component xModuleEven = xRingModules.child(_Unicode(moduleEven));
88 Component xModuleProperties = xRing.child(_Unicode(moduleProperties));
89 Component xModulePropertiesComp =
90 xModuleProperties.child(_Unicode(components));
91 Component xSensorProperties = xRing.child(_Unicode(sensorProperties));
94 std::vector<std::pair<dd4hep::Material, double>> compMaterials;
96 for (dd4hep::xml::Collection_t xCompColl(xModulePropertiesComp,
98 nullptr != xCompColl; ++xCompColl) {
99 dd4hep::xml::Component xComp =
static_cast<Component
>(xCompColl);
101 compMaterials.push_back(std::make_pair(
102 lcdd.material(xComp.materialStr()), xComp.thickness()));
104 double integratedCompThickness = 0.;
105 for (dd4hep::xml::Collection_t xCompColl(xModulePropertiesComp,
107 nullptr != xCompColl; ++xCompColl) {
108 Component xComp =
static_cast<Component
>(xCompColl);
109 double compMinWidth =
110 0.5 * xModuleProperties.attr<
double>(
"modWidthMin");
111 double compMaxWidth =
112 0.5 * xModuleProperties.attr<
double>(
"modWidthMax");
113 double compThickness = 0.5 * xComp.thickness();
115 0.5 * xSensorProperties.attr<
double>(
"sensorLength");
116 Volume componentVolume(
118 dd4hep::Trapezoid(compMinWidth, compMaxWidth, compThickness,
119 compThickness, compLength),
120 lcdd.material(xComp.materialStr()));
124 compMinWidth, compMaxWidth, compLength, compThickness, xRing.X(),
127 componentVolume.setVisAttributes(lcdd.invisible());
128 unsigned int nPhi = xRing.attr<
int>(
"nModules");
130 for (
unsigned int phiIndex = 0; phiIndex < nPhi; ++phiIndex) {
135 double thetaTilt = 0;
136 if (0 == phiIndex % 2) {
139 phi = 2 *
dd4hep::pi *
static_cast<double>(phiIndex) /
140 static_cast<double>(nPhi);
141 lX = xModuleEven.X();
142 lY = xModuleEven.Y();
143 lZ = xModuleEven.Z() - xDisc.zmin() - discThickness;
144 phiTilt = xModuleEven.attr<
double>(
"phiTilt");
145 thetaTilt = xModuleEven.attr<
double>(
"thetaTilt");
149 lZ = xModuleOdd.Z() - xDisc.zmin() - discThickness;
150 phiTilt = xModuleOdd.attr<
double>(
"phiTilt");
151 thetaTilt = xModuleOdd.attr<
double>(
"thetaTilt");
155 dd4hep::RotationY lRotation1(
M_PI * 0.5);
156 dd4hep::RotationX lRotation2(
M_PI * 0.5 + phiTilt);
158 double componentOffset =
159 integratedCompThickness -
160 0.5 * xModuleProperties.attr<
double>(
"modThickness") +
161 0.5 * xComp.thickness();
162 dd4hep::RotationZ lRotation3(atan2(lY, lX));
165 dd4hep::RotationY lRotation4(thetaTilt -
M_PI * 0.5);
166 dd4hep::RotationZ lRotation_PhiPos(phi);
170 lRotation4 * lRotation3 * lRotation2 * lRotation1,
172 PlacedVolume placedComponentVolume =
173 discVolumeVec.back().placeVolume(componentVolume,
174 lRotation_PhiPos * myTrafo);
175 if (xComp.isSensitive()) {
176 placedComponentVolume.addPhysVolID(
"component", compCounter);
177 componentVolume.setSensitiveDetector(sensDet);
178 DetElement moduleDetElement(discDetElementVec.back(),
187 moduleDetElement.setPlacement(placedComponentVolume);
191 integratedCompThickness += xComp.thickness();
195 discDetElementVec.emplace_back(
196 discDetElementVec.back().clone(
"disc" +
std::to_string(discCounter)));
197 posEcapDetElement.add(discDetElementVec.back());
199 PlacedVolume placedDiscVolume = envelopeVolume.placeVolume(
200 discVolumeVec.back(), dd4hep::Position(0, 0, currentZ));
201 placedDiscVolume.addPhysVolID(
"disc", discCounter);
204 discDetElementVec.back().setPlacement(placedDiscVolume);
206 dd4hep::Assembly bothEndcaps(
"bothEndcapsEnvelope");
209 0, 0, dimensions.zmin() + envelopeThickness);
211 dd4hep::RotationX envelopeNegRotation(
dd4hep::pi);
212 dd4hep::RotationX envelopePosRotation(0.);
213 PlacedVolume placedEnvelopeVolume = bothEndcaps.placeVolume(
214 envelopeVolume, envelopePosRotation * envelopeTranslation);
215 PlacedVolume placedNegEnvelopeVolume = bothEndcaps.placeVolume(
216 envelopeVolume, envelopeNegRotation * envelopeTranslation);
217 placedEnvelopeVolume.addPhysVolID(
"posneg", 0);
218 placedNegEnvelopeVolume.addPhysVolID(
"posneg", 1);
219 auto negEcapDetElement = posEcapDetElement.clone(
"negEndcap");
221 posEcapDetElement.setPlacement(placedEnvelopeVolume);
222 negEcapDetElement.setPlacement(placedNegEnvelopeVolume);
223 worldDetElement.add(negEcapDetElement);
226 lcdd.pickMotherVolume(worldDetElement).placeVolume(bothEndcaps);
227 worldDetElement.setPlacement(mplv);
228 mplv.addPhysVolID(
"system", xmlDet.id());
229 return worldDetElement;