9 #include "../DetUtils.h"
11 #include "DD4hep/DetFactoryHelper.h"
13 using dd4hep::DetElement;
14 using dd4hep::PlacedVolume;
16 using dd4hep::xml::Component;
17 using dd4hep::xml::Dimension;
21 dd4hep::Detector& lcdd, dd4hep::xml::Handle_t xmlElement,
22 dd4hep::SensitiveDetector sensDet) {
24 dd4hep::xml::DetElement xmlDet =
25 static_cast<dd4hep::xml::DetElement
>(xmlElement);
26 Dimension dimensions(xmlDet.dimensions());
27 double l_overlapMargin = 0.01;
30 dd4hep::xml::Dimension sdTyp =
31 xmlElement.child(_Unicode(sensitive));
32 sensDet.setType(sdTyp.typeStr());
35 std::string detName = xmlDet.nameStr();
36 DetElement worldDetElement(detName, xmlDet.id());
37 DetElement posEcapDetElement(worldDetElement,
"posEndcap", 0);
40 ecapDetExt->
addType(
"endcap",
"detector");
43 dd4hep::Assembly envelopeVolume(
"endcapEnvelope");
44 envelopeVolume.setVisAttributes(lcdd.invisible());
46 Component xDiscs = xmlElement.child(_Unicode(discs));
48 double envelopeThickness = 0.5 * (dimensions.zmax() - dimensions.zmin());
50 l_overlapMargin *= 0.9;
52 unsigned int discCounter = 0;
53 unsigned int compCounter = 0;
55 std::vector<Volume> discVolumeVec;
56 std::vector<DetElement> discDetElementVec;
58 for (dd4hep::xml::Collection_t xDiscColl(xDiscs, _Unicode(discZPls));
59 nullptr != xDiscColl; ++xDiscColl) {
60 Component xDisc =
static_cast<Component
>(xDiscColl);
61 Component xCurrentRings = xDisc.child(_Unicode(rings));
63 double discThickness = 0.5 * (xDisc.zmax() - xDisc.zmin());
64 currentZ = xDisc.z() - dimensions.zmin() - envelopeThickness;
65 if (xCurrentRings.hasChild(
67 dd4hep::Tube discShape(xDisc.rmin() - l_overlapMargin,
68 xDisc.rmax() + l_overlapMargin,
69 discThickness + l_overlapMargin);
71 discVolumeVec.emplace_back(
"disc", discShape, lcdd.air());
72 discDetElementVec.emplace_back(
73 posEcapDetElement,
"disc" +
std::to_string(discCounter), discCounter);
77 detlayer->
addType(
"sensitive disk",
"layer");
78 detlayer->
addType(
"axes",
"definitions",
"XZY");
81 for (dd4hep::xml::Collection_t xRingColl(xCurrentRings, _U(ring));
82 (
nullptr != xRingColl); ++xRingColl) {
83 Component xRing =
static_cast<Component
>(xRingColl);
84 Component xRingModules = xRing.child(_Unicode(modules));
85 Component xModuleOdd = xRingModules.child(_Unicode(moduleOdd));
86 Component xModuleEven = xRingModules.child(_Unicode(moduleEven));
87 Component xModuleProperties = xRing.child(_Unicode(moduleProperties));
88 Component xModulePropertiesComp =
90 Component xSensorProperties = xRing.child(_Unicode(sensorProperties));
93 std::vector<std::pair<dd4hep::Material, double>> compMaterials;
95 for (dd4hep::xml::Collection_t xCompColl(xModulePropertiesComp,
97 nullptr != xCompColl; ++xCompColl) {
98 dd4hep::xml::Component xComp =
static_cast<Component
>(xCompColl);
100 compMaterials.push_back(std::make_pair(
101 lcdd.material(xComp.materialStr()), xComp.thickness()));
103 double integratedCompThickness = 0.;
104 for (dd4hep::xml::Collection_t xCompColl(xModulePropertiesComp,
106 nullptr != xCompColl; ++xCompColl) {
107 Component xComp =
static_cast<Component
>(xCompColl);
108 double compMinWidth =
109 0.5 * xModuleProperties.attr<
double>(
"modWidthMin");
110 double compMaxWidth =
111 0.5 * xModuleProperties.attr<
double>(
"modWidthMax");
112 double compThickness = 0.5 * xComp.thickness();
114 0.5 * xSensorProperties.attr<
double>(
"sensorLength");
115 Volume componentVolume(
117 dd4hep::Trapezoid(compMinWidth, compMaxWidth, compThickness,
118 compThickness, compLength),
119 lcdd.material(xComp.materialStr()));
123 compMinWidth, compMaxWidth, compLength, compThickness, xRing.X(),
126 componentVolume.setVisAttributes(lcdd.invisible());
127 unsigned int nPhi = xRing.attr<
int>(
"nModules");
129 for (
unsigned int phiIndex = 0; phiIndex < nPhi; ++phiIndex) {
134 double thetaTilt = 0;
135 if (0 == phiIndex % 2) {
138 phi = 2 *
dd4hep::pi *
static_cast<double>(phiIndex) /
139 static_cast<double>(nPhi);
140 lX = xModuleEven.X();
141 lY = xModuleEven.Y();
142 lZ = xModuleEven.Z() - xDisc.zmin() - discThickness;
143 phiTilt = xModuleEven.attr<
double>(
"phiTilt");
144 thetaTilt = xModuleEven.attr<
double>(
"thetaTilt");
148 lZ = xModuleOdd.Z() - xDisc.zmin() - discThickness;
149 phiTilt = xModuleOdd.attr<
double>(
"phiTilt");
150 thetaTilt = xModuleOdd.attr<
double>(
"thetaTilt");
154 dd4hep::RotationY lRotation1(
M_PI * 0.5);
155 dd4hep::RotationX lRotation2(
M_PI * 0.5 + phiTilt);
157 double componentOffset =
158 integratedCompThickness -
159 0.5 * xModuleProperties.attr<
double>(
"modThickness") +
160 0.5 * xComp.thickness();
161 dd4hep::RotationZ lRotation3(atan2(lY, lX));
164 dd4hep::RotationY lRotation4(thetaTilt -
M_PI * 0.5);
165 dd4hep::RotationZ lRotation_PhiPos(phi);
169 lRotation4 * lRotation3 * lRotation2 * lRotation1,
171 PlacedVolume placedComponentVolume =
172 discVolumeVec.back().placeVolume(componentVolume,
173 lRotation_PhiPos * myTrafo);
174 if (xComp.isSensitive()) {
175 placedComponentVolume.addPhysVolID(
"component", compCounter);
176 componentVolume.setSensitiveDetector(sensDet);
177 DetElement moduleDetElement(discDetElementVec.back(),
186 moduleDetElement.setPlacement(placedComponentVolume);
190 integratedCompThickness += xComp.thickness();
194 discDetElementVec.emplace_back(
195 discDetElementVec.back().clone(
"disc" +
std::to_string(discCounter)));
196 posEcapDetElement.add(discDetElementVec.back());
198 PlacedVolume placedDiscVolume = envelopeVolume.placeVolume(
199 discVolumeVec.back(), dd4hep::Position(0, 0, currentZ));
200 placedDiscVolume.addPhysVolID(
"disc", discCounter);
203 discDetElementVec.back().setPlacement(placedDiscVolume);
205 dd4hep::Assembly bothEndcaps(
"bothEndcapsEnvelope");
208 0, 0, dimensions.zmin() + envelopeThickness);
210 dd4hep::RotationX envelopeNegRotation(
dd4hep::pi);
211 dd4hep::RotationX envelopePosRotation(0.);
212 PlacedVolume placedEnvelopeVolume = bothEndcaps.placeVolume(
213 envelopeVolume, envelopePosRotation * envelopeTranslation);
214 PlacedVolume placedNegEnvelopeVolume = bothEndcaps.placeVolume(
215 envelopeVolume, envelopeNegRotation * envelopeTranslation);
216 placedEnvelopeVolume.addPhysVolID(
"posneg", 0);
217 placedNegEnvelopeVolume.addPhysVolID(
"posneg", 1);
218 auto negEcapDetElement = posEcapDetElement.clone(
"negEndcap");
220 posEcapDetElement.setPlacement(placedEnvelopeVolume);
221 negEcapDetElement.setPlacement(placedNegEnvelopeVolume);
222 worldDetElement.add(negEcapDetElement);
225 lcdd.pickMotherVolume(worldDetElement).placeVolume(bothEndcaps);
226 worldDetElement.setPlacement(mplv);
227 mplv.addPhysVolID(
"system", xmlDet.id());
228 return worldDetElement;