DD4hep  1.30.0
Detector Description Toolkit for High Energy Physics
Mask_o1_v01_geo.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 //==========================================================================
12 
14 #include "DD4hep/Printout.h"
15 #include "DD4hep/DD4hepUnits.h"
16 #include "DD4hep/DetType.h"
17 #include "DDRec/DetectorData.h"
18 #include "XML/Utilities.h"
19 
20 #include <cmath>
21 #include <string>
22 
24 using dd4hep::Position;
25 using dd4hep::RotationX;
26 using dd4hep::RotationY;
27 using dd4hep::RotateY;
28 using dd4hep::RotateX;
31 using dd4hep::Material;
32 using dd4hep::Volume;
33 using dd4hep::Solid;
34 using dd4hep::Tube;
36 using dd4hep::Assembly;
37 using dd4hep::Detector;
39 using dd4hep::Ref_t;
40 
41 namespace units = dd4hep;
42 
43 
44 static Ref_t create_detector(Detector& description,
45  xml_h xmlHandle,
46  SensitiveDetector sens) {
47 
48  printout(dd4hep::DEBUG,"DD4hep_Mask", "Creating Mask" ) ;
49 
50  //Access to the XML File
51  xml_det_t xmlMask = xmlHandle;
52  const std::string name = xmlMask.nameStr();
53 
54  //--------------------------------
55  Assembly envelope( name + "_assembly" ) ;
56  //--------------------------------
57 
58  dd4hep::DetElement tube( name, xmlMask.id() ) ;
59 
60  bool rotationX= false;
61 
62  //Parameters we have to know about
63  dd4hep::xml::Component xmlParameter = xmlMask.child(_Unicode(parameter));
64  const double crossingAngle = xmlParameter.attr< double >(_Unicode(crossingangle))*0.5; // only half the angle
65 
66  if (xmlParameter.hasAttr(_Unicode(rotationX)))
67  rotationX = xmlParameter.attr< bool >(_Unicode(rotationX));
68 
69  int counter = 0;
70  for(xml_coll_t c( xmlMask ,Unicode("section")); c; ++c, counter++) {
71 
72  xml_comp_t xmlSection( c );
73  bool isSensitive = false;
74  ODH::ECrossType crossType = ODH::getCrossType(xmlSection.attr< std::string >(_Unicode(type)));
75  const double zStart = xmlSection.attr< double > (_Unicode(start));
76  const double zEnd = xmlSection.attr< double > (_Unicode(end));
77  const double rInnerStart = xmlSection.attr< double > (_Unicode(rMin1));
78  const double rInnerEnd = xmlSection.attr< double > (_Unicode(rMin2));
79  const double rOuterStart = xmlSection.attr< double > (_Unicode(rMax1));
80  const double rOuterEnd = xmlSection.attr< double > (_Unicode(rMax2));
81  const double thickness = rOuterStart - rInnerStart;
82  Material sectionMat = description.material(xmlSection.materialStr());
83  const std::string volName = "tube_" + xmlSection.nameStr();
84 
85  double phi1 = 0 ;
86  double phi2 = 360.0*units::degree;
87  if (xmlSection.hasAttr(_U(phi1)))
88  phi1 = xmlSection.attr< double > (_U(phi1));
89  if (xmlSection.hasAttr(_U(phi2)))
90  phi2 = xmlSection.attr< double > (_U(phi2));
91 
92  std::string ssensitive = "none";
93  if (xmlSection.hasAttr(_U(sensitive))){
94  isSensitive = true;
95  ssensitive = xmlSection.attr< std::string > (_U(sensitive));
96  sens.setType( xmlSection.attr< std::string > (_U(sensitive)) ); //decide the type of SD (tracker / calorimeter) check for k4run
97  printout(dd4hep::DEBUG, "sensitive in sens ", ssensitive);
98  }
99 
100 
101  std::stringstream pipeInfo;
102  pipeInfo << std::setw(8) << zStart /units::mm
103  << std::setw(8) << zEnd /units::mm
104  << std::setw(8) << rInnerStart /units::mm
105  << std::setw(8) << rInnerEnd /units::mm
106  << std::setw(8) << rOuterStart /units::mm
107  << std::setw(8) << rOuterEnd /units::mm
108  << std::setw(8) << thickness /units::mm
109  << std::setw(8) << crossType
110  << std::setw(35) << volName
111  << std::setw(15) << sectionMat.name()
112  << std::setw(8) << phi1
113  << std::setw(8) << phi2
114  << std::setw(8) << ssensitive;
115 
116  printout(dd4hep::INFO, "DD4hep_Mask", pipeInfo.str() );
117 
118  // things which can be calculated immediately
119  const double zHalf = fabs(zEnd - zStart) * 0.5; // half z length of the cone
120  const double zPosition = fabs(zEnd + zStart) * 0.5; // middle z position
121  Material material = sectionMat;
122 
123  // this could mess up your geometry, so better check it
124  if (not ODH::checkForSensibleGeometry(crossingAngle, crossType)){
125  throw std::runtime_error( " Mask_o1_v01_geo.cpp : checkForSensibleGeometry() failed " ) ;
126  }
127 
128  const double rotateAngle = getCurrentAngle(crossingAngle, crossType); // for the placement at +z (better make it const now)
129  const double mirrorAngle = M_PI - rotateAngle; // for the "mirrored" placement at -z
130  // the "mirroring" in fact is done by a rotation of (almost) 180 degrees around the y-axis
131 
132 
133  switch (crossType) {
134  case ODH::kCenter:
135  case ODH::kUpstream:
136  case ODH::kDnstream: {
137  // a volume on the z-axis, on the upstream branch, or on the downstream branch
138  Transform3D transformer, transmirror;
139 
140  if( rotationX == true) {
141  // absolute transformations for the placement in the world, rotate over X
142  transformer = Transform3D(RotationX(rotateAngle), RotateX( Position(0, 0, zPosition), rotateAngle) );
143  transmirror = Transform3D(RotationX(mirrorAngle), RotateX( Position(0, 0, zPosition), mirrorAngle) );
144  } else{
145  // absolute transformations for the placement in the world
146  transformer = Transform3D(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition), rotateAngle) );
147  transmirror = Transform3D(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition), mirrorAngle) );
148  }
149 
150  // solid for the tube (including vacuum and wall): a solid cone
151  ConeSegment tubeSolid( zHalf, rInnerStart, rOuterStart, rInnerEnd, rOuterEnd , phi1, phi2);
152 
153  // tube consists of vacuum
154  Volume tubeLog0( volName, tubeSolid, material ) ;
155  Volume tubeLog1( volName, tubeSolid, material ) ;
156  if (isSensitive) {
157  tubeLog0.setSensitiveDetector(sens);
158  tubeLog1.setSensitiveDetector(sens);
159  }
160  tubeLog0.setVisAttributes(description, xmlMask.visStr() );
161  tubeLog1.setVisAttributes(description, xmlMask.visStr() );
162 
163  // placement of the tube in the world, both at +z and -z
164  PlacedVolume placed0 = envelope.placeVolume( tubeLog0, transformer );
165  PlacedVolume placed1 = envelope.placeVolume( tubeLog1, transmirror );
166 
167  placed0.addPhysVolID("side",1);
168  placed0.addPhysVolID("layer",counter);
169  placed1.addPhysVolID("side",-1);
170  placed1.addPhysVolID("layer",counter);
171 
172  }
173  break;
174 
175  case ODH::kPunchedCenter: {
176  // a cone with one or two inner holes (two tubes are punched out)
177 
178  const double rUpstreamPunch = rInnerStart; // just alias names denoting what is meant here
179  const double rDnstreamPunch = rInnerEnd; // (the database entries are "abused" in this case)
180 
181  // relative transformations for the composition of the SubtractionVolumes
182  Transform3D upstreamTransformer(RotationY(-crossingAngle), Position(zPosition * tan(-crossingAngle), 0, 0));
183  Transform3D dnstreamTransformer(RotationY(+crossingAngle), Position(zPosition * tan(+crossingAngle), 0, 0));
184 
185  // absolute transformations for the final placement in the world (angles always equal zero and 180 deg)
186  Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition) , rotateAngle) );
187  Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition) , mirrorAngle) );
188 
189  // the main solid and the two pieces (only tubes, for the moment) which will be punched out
190  ConeSegment wholeSolid( zHalf, 0, rOuterStart, 0, rOuterEnd, phi1, phi2 );
191  Solid tmpSolid0, tmpSolid1, finalSolid0, finalSolid1;
192 
193  // the punched subtraction solids can be asymmetric and therefore have to be created twice:
194  // one time in the "right" way, another time in the "reverse" way, because the "mirroring"
195  // rotation around the y-axis will not only exchange +z and -z, but also +x and -x
196 
197  if ( rUpstreamPunch > 1e-6 ) { // do we need a hole on the upstream branch?
198  Tube upstreamPunch( 0, rUpstreamPunch, 5 * zHalf, phi1, phi2); // a bit longer
199  tmpSolid0 = SubtractionSolid( wholeSolid, upstreamPunch, upstreamTransformer);
200  tmpSolid1 = SubtractionSolid( wholeSolid, upstreamPunch, dnstreamTransformer); // [sic]
201  } else { // dont't do anything, just pass on the unmodified shape
202  tmpSolid0 = wholeSolid;
203  tmpSolid1 = wholeSolid;
204  }
205 
206  if (rDnstreamPunch > 1e-6 ) { // do we need a hole on the downstream branch?
207  Tube dnstreamPunch( 0, rDnstreamPunch, 5 * zHalf, phi1, phi2); // a bit longer
208  finalSolid0 = SubtractionSolid( tmpSolid0, dnstreamPunch, dnstreamTransformer);
209  finalSolid1 = SubtractionSolid( tmpSolid1, dnstreamPunch, upstreamTransformer); // [sic]
210  } else { // dont't do anything, just pass on the unmodified shape
211  finalSolid0 = tmpSolid0;
212  finalSolid1 = tmpSolid1;
213  }
214 
215  // tube consists of vacuum (will later have two different daughters)
216  Volume tubeLog0( volName + "_0", finalSolid0, material );
217  Volume tubeLog1( volName + "_1", finalSolid1, material );
218  if (isSensitive) {
219  tubeLog0.setSensitiveDetector(sens);
220  tubeLog1.setSensitiveDetector(sens);
221  }
222  tubeLog0.setVisAttributes(description, xmlMask.visStr() );
223  tubeLog1.setVisAttributes(description, xmlMask.visStr() );
224 
225  // placement of the tube in the world, both at +z and -z
226  PlacedVolume placed0 = envelope.placeVolume( tubeLog0, placementTransformer );
227  PlacedVolume placed1 = envelope.placeVolume( tubeLog1, placementTransmirror );
228 
229  placed0.addPhysVolID("side", 1);
230  placed1.addPhysVolID("side", -1);
231  placed0.addPhysVolID("layer", counter);
232  placed1.addPhysVolID("layer", counter);
233 
234  break;
235  }
236 
238  case ODH::kPunchedDnstream: {
239  // a volume on the upstream or downstream branch with two inner holes
240  // (implemented as a cone from which another tube is punched out)
241 
242  const double rCenterPunch = (crossType == ODH::kPunchedUpstream) ? (rInnerStart) : (rInnerEnd); // just alias names denoting what is meant here
243  const double rOffsetPunch = (crossType == ODH::kPunchedDnstream) ? (rInnerStart) : (rInnerEnd); // (the database entries are "abused" in this case)
244 
245  // relative transformations for the composition of the SubtractionVolumes
246  Transform3D punchTransformer(RotationY(-2 * rotateAngle), Position(zPosition * tan(-2 * rotateAngle), 0, 0));
247  Transform3D punchTransmirror(RotationY(+2 * rotateAngle), Position(zPosition * tan(+2 * rotateAngle), 0, 0));
248 
249  // absolute transformations for the final placement in the world
250  Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition) , rotateAngle) );
251  Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition) , mirrorAngle) );
252 
253  // the main solid and the piece (only a tube, for the moment) which will be punched out
254  ConeSegment wholeSolid( zHalf, rCenterPunch , rOuterStart, rCenterPunch, rOuterEnd, phi1, phi2);
255  Tube punchSolid( 0, rOffsetPunch, 5 * zHalf, phi1, phi2); // a bit longer
256 
257  // the punched subtraction solids can be asymmetric and therefore have to be created twice:
258  // one time in the "right" way, another time in the "reverse" way, because the "mirroring"
259  // rotation around the y-axis will not only exchange +z and -z, but also +x and -x
260  SubtractionSolid finalSolid0( wholeSolid, punchSolid, punchTransformer);
261  SubtractionSolid finalSolid1( wholeSolid, punchSolid, punchTransmirror);
262 
263  // tube consists of vacuum (will later have two different daughters)
264  Volume tubeLog0( volName + "_0", finalSolid0, material );
265  Volume tubeLog1( volName + "_1", finalSolid1, material );
266  if (isSensitive) {
267  tubeLog0.setSensitiveDetector(sens);
268  tubeLog1.setSensitiveDetector(sens);
269  }
270  tubeLog0.setVisAttributes(description, xmlMask.visStr() );
271  tubeLog1.setVisAttributes(description, xmlMask.visStr() );
272 
273  // placement of the tube in the world, both at +z and -z
274  PlacedVolume placed0 = envelope.placeVolume( tubeLog0, placementTransformer );
275  PlacedVolume placed1 = envelope.placeVolume( tubeLog1, placementTransmirror );
276 
277  placed0.addPhysVolID("side", 1);
278  placed1.addPhysVolID("side", -1);
279  placed0.addPhysVolID("layer", counter);
280  placed1.addPhysVolID("layer", counter);
281 
282  break;
283  }
284  default: {
285  throw std::runtime_error( " Mask_o1_v01_geo.cpp : fatal failure !! ?? " ) ;
286  }
287 
288  }//end switch
289 
290  }//for all xmlSections
291 
292  //--------------------------------------
293  Volume mother = description.pickMotherVolume( tube ) ;
294  PlacedVolume pv(mother.placeVolume(envelope));
295  pv.addPhysVolID( "system", xmlMask.id() ) ; //.addPhysVolID("side", 0 ) ;
296 
297  tube.setVisAttributes( description, xmlMask.visStr(), envelope );
298 
299  tube.setPlacement(pv);
300 
301  return tube;
302 }
303 DECLARE_DETELEMENT(DD4hep_Mask_o1_v01,create_detector)
dd4hep::xml::Collection_t
Class to support the access to collections of XmlNodes (or XmlElements)
Definition: XMLElements.h:636
ODH::kCenter
@ kCenter
Definition: OtherDetectorHelpers.h:23
DetectorData.h
dd4hep::SensitiveDetector
Handle class to hold the information of a sensitive detector.
Definition: DetElement.h:44
DECLARE_DETELEMENT
#define DECLARE_DETELEMENT(name, func)
Definition: Factories.h:339
M_PI
#define M_PI
Definition: Handle.h:33
ODH::kPunchedUpstream
@ kPunchedUpstream
Definition: OtherDetectorHelpers.h:27
dd4hep::PlacedVolume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:173
dd4hep::PlacedVolume::addPhysVolID
PlacedVolume & addPhysVolID(const std::string &name, int value)
Add identifier.
Definition: Volumes.cpp:485
dd4hep::Detector::pickMotherVolume
virtual Volume pickMotherVolume(const DetElement &sd) const =0
Access mother volume by detector element.
dd4hep::xml::Handle_t
Class to easily access the properties of single XmlElements.
Definition: XMLElements.h:380
dd4hep::Handle::name
const char * name() const
Access the object name (or "" if not supported by the object)
DetType.h
dd4hep::Assembly
Implementation class extending the ROOT assembly volumes (TGeoVolumeAssembly)
Definition: Volumes.h:762
dd4hep::Volume::placeVolume
PlacedVolume placeVolume(const Volume &volume) const
Place daughter volume. The position and rotation are the identity.
Definition: Volumes.cpp:830
dd4hep::RotateY
V RotateY(const V &v, double a)
Definition: Objects.h:88
dd4hep::ConeSegment
Class describing a cone segment shape.
Definition: Shapes.h:542
xml_comp_t
dd4hep::xml::Component xml_comp_t
Definition: XML.h:33
_Unicode
#define _Unicode(a)
Definition: Tags.h:24
dd4hep::Material
Handle class describing a material.
Definition: Objects.h:272
ODH::ECrossType
ECrossType
Definition: OtherDetectorHelpers.h:22
dd4hep::Detector::material
virtual Material material(const std::string &name) const =0
Retrieve a matrial by its name from the detector description.
dd4hep::DetElement
Handle class describing a detector element.
Definition: DetElement.h:188
dd4hep::Volume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:378
Unicode
dd4hep::xml::Strng_t Unicode
Definition: XML.h:24
xml_det_t
dd4hep::xml::DetElement xml_det_t
Definition: XML.h:32
_U
#define _U(a)
Definition: Tags.h:23
dd4hep::RotateX
V RotateX(const V &v, double a)
Definition: Objects.h:85
ODH::kPunchedCenter
@ kPunchedCenter
Definition: OtherDetectorHelpers.h:26
dd4hep::Transform3D
ROOT::Math::Transform3D Transform3D
Definition: Objects.h:117
ODH::kPunchedDnstream
@ kPunchedDnstream
Definition: OtherDetectorHelpers.h:28
dd4hep::Position
ROOT::Math::XYZVector Position
Definition: Objects.h:81
dd4hep::RotationY
ROOT::Math::RotationY RotationY
Definition: Objects.h:109
dd4hep::Ref_t
Handle< NamedObject > Ref_t
Default Ref_t definition describing named objects.
Definition: Handle.h:182
DetFactoryHelper.h
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
dd4hep::Solid
Solid_type< TGeoShape > Solid
Definition: Shapes.h:197
ODH::kDnstream
@ kDnstream
Definition: OtherDetectorHelpers.h:25
dd4hep::Detector
The main interface to the dd4hep detector description package.
Definition: Detector.h:90
dd4hep::RotationX
ROOT::Math::RotationX RotationX
Definition: Objects.h:111
DD4hepUnits.h
dd4hep::Tube
Class describing a tube shape of a section of a tube.
Definition: Shapes.h:628
OtherDetectorHelpers.h
Printout.h
Utilities.h
dd4hep::SubtractionSolid
Class describing boolean subtraction solid.
Definition: Shapes.h:1878
dd4hep::SensitiveDetector::setType
SensitiveDetector & setType(const std::string &typ)
Set detector type (structure, tracker, calorimeter, etc.).
Definition: DetElement.cpp:403
ODH::kUpstream
@ kUpstream
Definition: OtherDetectorHelpers.h:24