CMS 3D CMS Logo

DD4hep_volumeHandle.cc
Go to the documentation of this file.
1 /*
2  * See header file for a description of this class.
3  *
4  * \author N. Amapane - INFN Torino (original developer)
5  */
6 
7 #include "DD4hep_volumeHandle.h"
8 
16 
17 #include <DD4hep/DD4hepUnits.h>
18 
19 #include <string>
20 #include <iterator>
21 
22 using namespace SurfaceOrientation;
23 using namespace std;
24 using namespace magneticfield;
25 using namespace edm;
26 
27 using DDBox = dd4hep::Box;
28 using DDTrap = dd4hep::Trap;
29 using DDTubs = dd4hep::Tube;
30 using DDCons = dd4hep::ConeSegment;
31 using DDTruncTubs = dd4hep::TruncatedTube;
32 
33 volumeHandle::volumeHandle(const cms::DDFilteredView &fv, bool expand2Pi, bool debugVal)
34  : BaseVolumeHandle(expand2Pi, debugVal), theShape(fv.legacyShape(fv.shape())), solid(fv) {
35  name = fv.name();
36  copyno = fv.copyNum();
37  const auto *const transArray = fv.trans();
38 
39  // Convert from DD4hep units to cm
40  center_ = GlobalPoint(transArray[0] / dd4hep::cm, transArray[1] / dd4hep::cm, transArray[2] / dd4hep::cm);
41 
42  // ASSUMPTION: volume names ends with "_NUM" where NUM is the volume number
43  string volName = name;
44  volName.erase(0, volName.rfind('_') + 1);
45  volumeno = static_cast<unsigned short>(std::atoi(volName.c_str()));
46 
47  for (int i = 0; i < 6; ++i) {
48  isAssigned[i] = false;
49  }
50  referencePlane(fv);
51  switch (theShape) {
52  case DDSolidShape::ddbox: {
53  DDBox box(solid.solid());
54  // Convert from DD4hep units to cm
55  double halfX = box.x() / dd4hep::cm;
56  double halfY = box.y() / dd4hep::cm;
57  double halfZ = box.z() / dd4hep::cm;
58  buildBox(halfX, halfY, halfZ);
59  } break;
60  case DDSolidShape::ddtrap: {
61  DDTrap trap(solid.solid());
62  double x1 = trap.bottomLow1() / dd4hep::cm;
63  double x2 = trap.topLow1() / dd4hep::cm;
64  double x3 = trap.bottomLow2() / dd4hep::cm;
65  double x4 = trap.topLow2() / dd4hep::cm;
66  double y1 = trap.high1() / dd4hep::cm;
67  double y2 = trap.high2() / dd4hep::cm;
68  double theta = trap.theta();
69  double phi = trap.phi();
70  double halfZ = trap.dZ() / dd4hep::cm;
71  double alpha1 = trap.alpha1();
72  double alpha2 = trap.alpha2();
73  buildTrap(x1, x2, x3, x4, y1, y2, theta, phi, halfZ, alpha1, alpha2);
74  } break;
75 
76  case DDSolidShape::ddcons: {
77  DDCons cons(solid.solid());
78  double zhalf = cons.dZ() / dd4hep::cm;
79  double rInMinusZ = cons.rMin1() / dd4hep::cm;
80  double rOutMinusZ = cons.rMax1() / dd4hep::cm;
81  double rInPlusZ = cons.rMin2() / dd4hep::cm;
82  double rOutPlusZ = cons.rMax2() / dd4hep::cm;
83  double startPhi = cons.startPhi();
84  double deltaPhi = reco::deltaPhi(cons.endPhi(), startPhi);
85  buildCons(zhalf, rInMinusZ, rOutMinusZ, rInPlusZ, rOutPlusZ, startPhi, deltaPhi);
86  } break;
87  case DDSolidShape::ddtubs: {
88  DDTubs tubs(solid.solid());
89  double zhalf = tubs.dZ() / dd4hep::cm;
90  double rIn = tubs.rMin() / dd4hep::cm;
91  double rOut = tubs.rMax() / dd4hep::cm;
92  double startPhi = tubs.startPhi();
93  double deltaPhi = tubs.endPhi() - startPhi;
94  buildTubs(zhalf, rIn, rOut, startPhi, deltaPhi);
95  } break;
97  vector<double> d = solid.parameters();
98 
99  // The pseudo-trapezoid parameters are:
100  // d[0] -- x1
101  // d[1] -- x2
102  // d[2] -- y1
103  // d[3] -- y2
104  // d[4] -- halfZ
105  // d[5] -- radius
106  // d[6] -- atMinusZ (0 or 1)
107  // Note all are lengths except for the last one. The lengths come from
108  // DD4hep in DD4hep units and must be converted to cm for use.
109 
110  if (d.size() >= 7)
111  LogTrace("MagGeoBuilder") << " Pseudo trap params raw = " << d[0] << ", " << d[1] << ", " << d[2] << ", "
112  << d[3] << ", " << d[4] << ", " << d[5] << ", " << d[6];
113 
114  // Convert all but last parameter to cm (last one is a boolean).
115  transform(d.begin(), --(d.end()), d.begin(), [](double val) { return val / dd4hep::cm; });
116 
117  if (d.size() >= 7)
118  LogTrace("MagGeoBuilder") << " Pseudo trap params converted = " << d[0] << ", " << d[1] << ", " << d[2] << ", "
119  << d[3] << ", " << d[4] << ", " << d[5] << ", " << d[6];
120 
121  buildPseudoTrap(d[0], d[1], d[2], d[3], d[4], d[5], static_cast<bool>(d[6]));
122  } break;
124  DDTruncTubs tubs(solid.solid());
125  double zhalf = tubs.dZ() / dd4hep::cm; // half of the z-Axis
126  double rIn = tubs.rMin() / dd4hep::cm; // inner radius
127  double rOut = tubs.rMax() / dd4hep::cm; // outer radius
128  double startPhi = tubs.startPhi(); // angular start of the tube-section
129  double deltaPhi = tubs.deltaPhi(); // angular span of the tube-section
130  double cutAtStart = tubs.cutAtStart() / dd4hep::cm; // truncation at begin of the tube-section
131  double cutAtDelta = tubs.cutAtDelta() / dd4hep::cm; // truncation at end of the tube-section
132  bool cutInside = tubs.cutInside(); // true, if truncation is on the inner side of the tube-section
133  buildTruncTubs(zhalf, rIn, rOut, startPhi, deltaPhi, cutAtStart, cutAtDelta, cutInside);
134  } break;
135  default:
136  LogError("magneticfield::volumeHandle")
137  << "ctor: Unexpected shape # " << static_cast<int>(theShape) << " for vol " << name;
138  }
139 
140  // The only materials used in the geometry are: materials:Air, d=0.001214; materials:Iron, d=7.87
141  if (fv.volume().material().density() > 3.)
142  isIronFlag = true;
143 
144  if (debug) {
145  LogTrace("MagGeoBuilder") << " RMin = " << theRMin << newln << " RMax = " << theRMax;
146 
147  if (theRMin < 0 || theRN < theRMin || theRMax < theRN)
148  LogTrace("MagGeoBuilder") << "*** WARNING: wrong RMin/RN/RMax";
149 
150  LogTrace("MagGeoBuilder") << "Summary: " << name << " " << copyno << " shape = " << theShape << " trasl "
151  << center() << " R " << center().perp() << " phi " << center().phi() << " magFile "
152  << magFile << " Material= " << fv.materialName() << " isIron= " << isIronFlag
153  << " masterSector= " << masterSector;
154 
155  LogTrace("MagGeoBuilder") << " Orientation of surfaces:";
156  std::string sideName[3] = {"positiveSide", "negativeSide", "onSurface"};
157  for (int i = 0; i < 6; ++i) {
158  if (surfaces[i] != nullptr)
159  LogTrace("MagGeoBuilder") << " " << i << ":" << sideName[surfaces[i]->side(center_, 0.3)];
160  }
161  }
162 }
163 
165  // The refPlane is the "main plane" for the solid. It corresponds to the
166  // x,y plane in the DDD local frame, and defines a frame where the local
167  // coordinates are the same as in DDD.
168  // In the geometry version 85l_030919, this plane is normal to the
169  // beam line for all volumes but pseudotraps, so that global R is along Y,
170  // global phi is along -X and global Z along Z:
171  //
172  // Global(for vol at pi/2) Local
173  // +R (+Y) +Y
174  // +phi(-X) -X
175  // +Z +Z
176  //
177  // For pseudotraps the refPlane is parallel to beam line and global R is
178  // along Z, global phi is along +-X and and global Z along Y:
179  //
180  // Global(for vol at pi/2) Local
181  // +R (+Y) +Z
182  // +phi(-X) +X
183  // +Z +Y
184  //
185  // Note that the frame is centered in the DDD volume center, which is
186  // inside the volume for DDD boxes and (pesudo)trapezoids, on the beam line
187  // for tubs, cons and trunctubs.
188 
189  // In geometry version 1103l, trapezoids have X and Z in the opposite direction
190  // than the above. Boxes are either oriented as described above or in some case
191  // have opposite direction for Y and X.
192 
193  // The global position
194  Surface::PositionType &posResult = center_;
195 
196  // The reference plane rotation
197  math::XYZVector x, y, z;
198  dd4hep::Rotation3D refRot;
199  fv.rot(refRot);
200  refRot.GetComponents(x, y, z);
201  if (debug) {
202  if (x.Cross(y).Dot(z) < 0.5) {
203  LogTrace("MagGeoBuilder") << "*** WARNING: Rotation is not RH ";
204  }
205  }
206 
207  // The global rotation
208  Surface::RotationType rotResult(float(x.X()),
209  float(x.Y()),
210  float(x.Z()),
211  float(y.X()),
212  float(y.Y()),
213  float(y.Z()),
214  float(z.X()),
215  float(z.Y()),
216  float(z.Z()));
217 
218  refPlane = new GloballyPositioned<float>(posResult, rotResult);
219 
220  // Check correct orientation
221  if (debug) {
222  LogTrace("MagGeoBuilder") << "Refplane pos " << refPlane->position();
223 
224  // See comments above for the conventions for orientation.
225  LocalVector globalZdir(0., 0., 1.); // Local direction of the axis along global Z
226 
228  globalZdir = LocalVector(0., 1., 0.);
229  }
230 
231  if (refPlane->toGlobal(globalZdir).z() < 0.) {
232  globalZdir = -globalZdir;
233  }
234  float chk = refPlane->toGlobal(globalZdir).dot(GlobalVector(0, 0, 1));
235  if (chk < .999)
236  LogTrace("MagGeoBuilder") << "*** WARNING RefPlane check failed!***" << chk;
237  }
238 }
239 
240 std::vector<VolumeSide> volumeHandle::sides() const {
241  std::vector<VolumeSide> result;
242  for (int i = 0; i < 6; ++i) {
243  // If this is just a master volume out of wich a 2pi volume
244  // should be built (e.g. central cylinder), skip the phi boundaries.
245  if (expand && (i == phiplus || i == phiminus))
246  continue;
247 
248  // FIXME: Skip null inner degenerate cylindrical surface
250  continue;
251 
252  ReferenceCountingPointer<Surface> s = const_cast<Surface *>(surfaces[i].get());
253  result.push_back(VolumeSide(s, GlobalFace(i), surfaces[i]->side(center_, 0.3)));
254  }
255  return result;
256 }
257 
258 #include "buildBox.icc"
259 #include "buildTrap.icc"
260 #include "buildTubs.icc"
261 #include "buildCons.icc"
262 #include "buildPseudoTrap.icc"
263 #include "buildTruncTubs.icc"
GlobalPoint toGlobal(const LocalPoint &lp) const
constexpr double deltaPhi(double phi1, double phi2)
Definition: deltaPhi.h:26
void buildBox(double halfX, double halfY, double halfZ)
MagGeoBuilderFromDDD::volumeHandle volumeHandle
T perp() const
Definition: PV3DBase.h:69
A truncated tube section.
Definition: DDSolid.h:139
double startPhi(void) const
angular start of the tube-section
Definition: DDSolid.cc:172
Surface::LocalVector LocalVector
T z() const
Definition: PV3DBase.h:61
Geom::Phi< T > phi() const
Definition: PV3DBase.h:66
const Double_t * rot() const
The absolute rotation of the current node.
Log< level::Error, false > LogError
const GlobalPoint & center() const
Return the center of the volume.
unsigned short volumeno
volume number
const char *const newln
#define LogTrace(id)
unsigned short copyno
copy number
std::string_view name() const
const Double_t * trans() const
The absolute translation of the current node.
GloballyPositioned< float > * refPlane
void referencePlane(const cms::DDFilteredView &fv)
Surface::GlobalPoint GlobalPoint
void buildTrap(double x1, double x2, double x3, double x4, double y1, double y2, double theta, double phi, double halfZ, double alpha1, double alpha2)
void buildTruncTubs(double zhalf, double rIn, double rOut, double startPhi, double deltaPhi, double cutAtStart, double cutAtDelta, bool cutInside)
Interface to a Trapezoid.
Definition: DDSolid.h:88
int masterSector
The sector for which an interpolator for this class of volumes should be built.
std::string_view materialName() const
unsigned short copyNum() const
d
Definition: ztail.py:151
void buildPseudoTrap(double x1, double x2, double y1, double y2, double halfZ, double radius, bool atMinusZ)
const PositionType & position() const
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:31
Interface to a Box.
Definition: DDSolid.h:167
std::string name
Name of the volume.
void buildCons(double zhalf, double rInMinusZ, double rOutMinusZ, double rInPlusZ, double rOutPlusZ, double startPhi, double deltaPhi)
dd4hep::Solid solid() const
HLT enums.
double startPhi(void) const
Definition: DDSolid.cc:460
const PlacedVolume volume() const
The physical volume of the current node.
std::vector< VolumeSide > sides() const override
The surfaces and they orientation, as required to build a MagVolume.
float x
const std::vector< double > parameters() const
extract shape parameters
Geom::Theta< T > theta() const
std::string magFile
Name of magnetic field table file.
const cms::DDFilteredView & solid
Global3DVector GlobalVector
Definition: GlobalVector.h:10
void buildTubs(double zhalf, double rIn, double rOut, double startPhi, double deltaPhi)
unsigned transform(const HcalDetId &id, unsigned transformCode)