ATLAS Offline Software
Loading...
Searching...
No Matches
MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MdtReadoutElement.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
5
7#include <GeoModelHelpers/TransformToStringConverter.h>
10#include <GaudiKernel/SystemOfUnits.h>
11
12#include <optional>
13
14
15#ifndef SIMULATIONBASE
17# include "Acts/Surfaces/TrapezoidBounds.hpp"
18# include "Acts/Surfaces/LineBounds.hpp"
19# include "Acts/Surfaces/Surface.hpp"
20#endif
21
22using namespace ActsTrk;
23
24namespace MuonGMR4 {
25std::ostream& operator<<(std::ostream& ostr, const MuonGMR4::MdtReadoutElement::parameterBook& pars) {
26 ostr << std::endl;
27 ostr << " // Chamber half- length (min/max): "<<pars.shortHalfX<<"/"<<pars.longHalfX
28 <<", half-width "<<pars.halfY<<", height: "<<pars.halfHeight;
29 ostr << " // Number of tube layers " << pars.tubeLayers.size()<< std::endl;
30 ostr << " // Tube pitch: " << pars.tubePitch
31 << " wall thickness: " << pars.tubeWall
32 << " inner radius: " << pars.tubeInnerRad
33 << " endplug: "<<pars.endPlugLength
34 << " deadlength: "<<pars.deadLength<< std::endl;
35 for (const MdtTubeLayerPtr& layer : pars.tubeLayers) {
36 ostr << " // **** "<< Amg::toString(layer->tubeTransform(0).translation(), 2)<<std::endl;
37 }
38 return ostr;
39}
47 return m_idHelper.channelID(identify(), multilayer(),
48 layerNumber(measHash) + 1,
49 tubeNumber(measHash) + 1);
50}
54 if (!numLayers() || !numTubesInLay()) {
55 ATH_MSG_FATAL("The readout element "<< idHelperSvc()->toStringDetEl(identify())<<" has no tubes. Please check "<<std::endl<<m_pars);
56 return StatusCode::FAILURE;
57 }
58 if (m_pars.tubePitch<=tubeRadius()) {
59 ATH_MSG_FATAL("The tubes of "<<idHelperSvc()->toStringDetEl(identify())<<" will fall together on a single point. Please check "<<std::endl<<m_pars);
60 return StatusCode::FAILURE;
61 }
62#ifndef SIMULATIONBASE
64 ATH_CHECK(planeSurfaceFactory(geoTransformHash(), m_pars.boundFactory->makeBounds<Acts::TrapezoidBounds>(m_pars.shortHalfX,
65 m_pars.longHalfX,
66 m_pars.halfY)));
67#endif
70
71 std::optional<Amg::Vector3D> prevLayPos{std::nullopt};
72
73 for (unsigned int lay =1 ; lay <= numLayers() ; ++lay) {
75 const IdentifierHash layHash = measurementHash(lay,0);
77#ifdef SIMULATIONBASE_REMOVEPLANESURFACE
78 ATH_CHECK(planeSurfaceFactory(layHash, m_pars.boundFactory->makeBounds<Acts::TrapezoidBounds>(m_pars.shortHalfX,
79 m_pars.longHalfX,
80 m_pars.halfY)));
81#endif
83 std::optional<Amg::Vector3D> prevTubePos{std::nullopt};
84 MdtTubeLayer& layer = *m_pars.tubeLayers[lay-1];
85
86 for (unsigned int tube = 1; tube <= numTubesInLay(); ++ tube) {
87 const IdentifierHash idHash = measurementHash(lay,tube);
88 if (m_pars.removedTubes.count(idHash)) {
89 prevTubePos = std::nullopt;
90 continue;
91 }
93#ifndef SIMULATIONBASE
94 ATH_CHECK(strawSurfaceFactory(idHash, m_pars.boundFactory->
95 makeBounds<Acts::LineBounds>(tubeRadius(),
96 0.5*tubeLength(idHash))));
97#endif
99 GeoTrf::Transform3D tubeFrame = layer.tubeTransform(tubeNumber(idHash));
100 const AmgSymMatrix(3) tubeRot = tubeFrame.linear();
101 if (std::abs(tubeRot.determinant()- 1.) > std::numeric_limits<float>::epsilon()){
102 ATH_MSG_FATAL(__FILE__<<":"<<__LINE__<<" Transformation matrix is not a pure rotation for "<<
103 idHelperSvc()->toStringDetEl(identify())<<" in layer: "<<lay<<", tube: "<<tube
104 <<Amg::toString(tubeFrame));
105 return StatusCode::FAILURE;
106 }
108 const Amg::Vector3D tubePos = tubeFrame.translation();
109
110 constexpr double pitchTolerance = 20. * Gaudi::Units::micrometer;
111 if (prevTubePos) {
112 const double dR = std::abs((tubePos - (*prevTubePos)).z());
113 if (std::abs(dR - tubePitch()) > pitchTolerance) {
114 ATH_MSG_FATAL(__FILE__<<":"<<__LINE__<<" Detected irregular tube in "<<
115 idHelperSvc()->toStringDetEl(identify())<<" in layer: "<<lay<<", tube: "<<tube
116 <<". Expected tube pitch: "<<tubePitch()<<" measured tube pitch: "
117 <<dR<<" tube position: "<<Amg::toString(tubePos,2)
118 <<" previous: "<<Amg::toString((*prevTubePos), 2));
119 return StatusCode::FAILURE;
120 }
121 }
122 if (prevLayPos && tube == 1) {
123 const double dR = (tubePos - (*prevLayPos)).mag();
124 if (std::abs(dR - tubePitch()) > pitchTolerance) {
125 ATH_MSG_FATAL(__FILE__<<":"<<__LINE__<<" Detected irregular layer pitch in "<<
126 idHelperSvc()->toStringDetEl(identify())<<" for layer "<<lay
127 <<". Expected tube pitch: "<<tubePitch()<<" measured tube pitch: "
128 <<dR<<" tube position: "<<Amg::toString(tubePos,2)
129 <<" previous:"<<Amg::toString((*prevLayPos), 2));
130 }
131 }
132 if (tube == 1) {
133 prevLayPos = std::make_optional<Amg::Vector3D>(tubePos);
134 }
135 prevTubePos = std::make_optional<Amg::Vector3D>(tubePos);
136 }
137 }
138#ifndef SIMULATIONBASE
139 m_pars.boundFactory.reset();
140#endif
141 return StatusCode::SUCCESS;
142}
143
145 const IdentifierHash& hash) const {
146 return localToGlobalTrans(ctx, hash).translation();
147}
148
150 return toTubeFrame(hash).translation();
151}
153 const IdentifierHash& hash) const {
154 return localToGlobalTrans(ctx, hash) *
155 (0.5*activeTubeLength(hash) * m_pars.readoutSide * Amg::Vector3D::UnitZ());
156}
158 const IdentifierHash& hash) const {
159 return localToGlobalTrans(ctx, hash) *
160 (-0.5*activeTubeLength(hash) * m_pars.readoutSide * Amg::Vector3D::UnitZ());
161}
163 const unsigned int layer = layerNumber(hash);
164 const MdtTubeLayer& zeroT{*m_pars.tubeLayers[layer]};
165 return zeroT.layerTransform();
166}
168 const unsigned int layer = layerNumber(hash);
169 const unsigned int tube = tubeNumber(hash);
170 const MdtTubeLayer& zeroT{*m_pars.tubeLayers[layer]};
171 return zeroT.tubeTransform(tube);
172}
174 const unsigned int layer = layerNumber(hash);
175 const unsigned int tube = tubeNumber(hash);
176 const MdtTubeLayer& zeroT{*m_pars.tubeLayers[layer]};
177 return 2. * zeroT.tubeHalfLength(tube);
178}
180 const unsigned int layer = layerNumber(tubeHash);
181 const unsigned int tube = tubeNumber(tubeHash);
182 const MdtTubeLayer& zeroT{*m_pars.tubeLayers[layer]};
183 return 2.*zeroT.uncutHalfLength(tube);
184}
186 return activeTubeLength(hash) + 2.*m_pars.deadLength;
187}
189 return tubeLength(hash) - 2.*m_pars.endPlugLength;
190}
192 const IdentifierHash& measHash,
193 const Amg::Vector3D& globPoint) const {
194 return distanceToReadout(measHash, globalToLocalTrans(ctx, measHash) * globPoint);
195
196}
198 const Amg::Vector3D& localPoint) const {
200 const unsigned int layer = layerNumber(measHash);
201 const unsigned int tube = tubeNumber(measHash);
202 const MdtTubeLayer& zeroT{*m_pars.tubeLayers[layer]};
203 const double readOutPos = m_pars.readoutSide * zeroT.tubeHalfLength(tube);
204 return std::abs(readOutPos - localPoint.z());
205}
206
210
211#if defined(FLATTEN)
212 // We compile this package with optimization, even in debug builds; otherwise,
213 // the heavy use of Eigen makes it too slow. However, from here we may call
214 // to out-of-line Eigen code that is linked from other DSOs; in that case,
215 // it would not be optimized. Avoid this by forcing all Eigen code
216 // to be inlined here if possible.
218#endif
220 return alignableTransform()->getDefTransform().inverse()*
221 getMaterialGeom()->getParent()->getX() *
222 getMaterialGeom()->getX();
223}
224
225#if defined(FLATTEN)
226 // We compile this package with optimization, even in debug builds; otherwise,
227 // the heavy use of Eigen makes it too slow. However, from here we may call
228 // to out-of-line Eigen code that is linked from other DSOs; in that case,
229 // it would not be optimized. Avoid this by forcing all Eigen code
230 // to be inlined here if possible.
232#endif
234 /* The fix point is the point that's closest to the interaction point.
235 / Recall that the readout element origin is expressed in the geometric centre &
236 the x-axis points upwards. The point is then transformed into the Muon station frame */
237 const MdtReadoutElement* refEle{multilayer() == 1 ? this : m_reOtherMl};
238 return refEle->asBuiltRefFrame()*(-0.5*( refEle->moduleThickness() *Amg::Vector3D::UnitX() +
239 (stationEta() >0 || !isBarrel() ? 1. : -1.)*refEle->moduleHeight() * Amg::Vector3D::UnitZ()));
240}
241#ifndef SIMULATIONBASE
242#if defined(FLATTEN)
243 // We compile this package with optimization, even in debug builds; otherwise,
244 // the heavy use of Eigen makes it too slow. However, from here we may call
245 // to out-of-line Eigen code that is linked from other DSOs; in that case,
246 // it would not be optimized. Avoid this by forcing all Eigen code
247 // to be inlined here if possible.
249#endif
251 const IdentifierHash& tubeHash,
252 const Amg::Vector3D& wireEnd,
253 const tubeSide_t side) const {
254
255
256 ATH_MSG_VERBOSE( "Applying as-built parameters for chamber " << idHelperSvc()->toString(measurementId(tubeHash)));
257
258
260 using multilayer_t = MdtAsBuiltPar::multilayer_t;
261 const multilayer_t ml = (multilayer() == 1) ? multilayer_t::ML1 : multilayer_t::ML2;
262
263 const IdentifierHash refLayer{measurementHash((ml == multilayer_t::ML1) ? numLayers() : 1, 1)};
264 const Amg::Vector3D refTube{localTubePos(refLayer)};
265
266
267 const double sideSign = 0.5*(1.- 2.*(side ==tubeSide_t::NEG));
268 // Compute the reference for the as-built parameters
269 const Amg::Vector3D reference_point = asBuiltRefFrame() *
270 Amg::Vector3D {refTube.x() + (1. - 2.*(ml == multilayer_t::ML2)) * tubeRadius(),
271 sideSign*uncutTubeLength(refLayer),
272 -0.5*moduleHeight()};
273 ATH_MSG_VERBOSE("AMDB transform "<<" "<<idHelperSvc()->toStringDetEl(identify())<<
274 " "<<GeoTrf::toString(asBuiltRefFrame(), true)<<", reference point: "<<Amg::toString(reference_point));
275
276
277 const int tubeLayer = layerNumber(tubeHash);
278 const int tube = tubeNumber(tubeHash);
279 const int layer_delta = ml == multilayer_t::ML1 ? numLayers() - tubeLayer : tubeLayer +1;
280
281
282 // Get the As-Built parameters for this ML and side of the chamber
283 const double zpitch = params.zpitch(ml, side);
284 const double ypitch = params.ypitch(ml, side);
285 const double stagg = params.stagg(ml, side);
286 const double alpha = params.alpha(ml, side);
287 const double y0 = params.y0(ml, side);
288 const double z0 = params.z0(ml, side);
289
290 const Amg::Transform3D planeRot{Amg::getRotateX3D(-alpha)};
291 ATH_MSG_VERBOSE("Rotation angle "<<(alpha/Gaudi::Units::deg));
292
293 // Find the vector from the reference_point to the endplug
294 // 0 for layer 1 and 3, 1 for layer 2 and 4
295 const double offset_stagg = 0.5 * zpitch * stagg * ( (layer_delta-1) % 2);
296 const Amg::Vector3D endPlug = planeRot * Amg::Vector3D{0.,
297 tube* zpitch + offset_stagg,
298 (layer_delta-1) * ypitch};
299
300 // Calculate x position, which varies for endcap chambers
301 const double xshift = sideSign*(uncutTubeLength(tubeHash) - uncutTubeLength(refLayer));
302 ATH_MSG_VERBOSE("Off set staggering "<<offset_stagg<<", layer_delta: "<<layer_delta<<", zpitch: "<<zpitch<<", ypitch: "<<ypitch
303 <<", xshift: "<<xshift);
304
305 Amg::Vector3D ret(reference_point.x() + xshift,
306 reference_point.y() + z0 + endPlug.y(),
307 reference_point.z() + y0 + endPlug.z());
308
309
310 if ((ret - wireEnd).mag() > 3. * Gaudi::Units::mm) {
311 ATH_MSG_WARNING("Large as-built correction for chamber " << idHelperSvc()->toString(measurementId(tubeHash))
312 << ", side "<< (side == tubeSide_t::POS ? "positive" : "negative")
313 << ", endpoint "<<Amg::toString(wireEnd)<<", return: "<<Amg::toString(ret));
314 }
315 ATH_MSG_VERBOSE((side == tubeSide_t::POS ? "positive" : "negative")<<" wire end has moved from "
316 <<Amg::toString(wireEnd)<<" to "<<Amg::toString(ret)<<" End plug: "<<Amg::toString(endPlug));
317 return ret;
318}
319
321 const Amg::Vector3D& localTubeEndPoint,
322 const Amg::Vector3D& fixedPoint,
323 const double chamberThickness) const {
324
325 using Parameter = BLinePar::Parameter;
326 Amg::Vector3D deformedPos{localTubeEndPoint};
327 // MDT deformations like tube bow: bz,bp,bn bend the tube while the wire endpoints are not affected
328 // => the wire keeps it's nominal straight line trajectory but it is not concentric to the tube
329 // ==> in this function bz, bp and bn are ignored or set to 0
330 // MDT deformations that extend/contract the wire longitudinally (while keeping it straight):
331 // delta_s from eg and tr are irrelevant for the tube geometry
332 // and for the wire trajectory => set to 0 here
333 // (should be applied as a correction to the
334 // tube lenght => tube surface bounds
335 // =++>>>> effect in tracking just through the gravitational sagging TOTALLY NEGLIGIBLE=> ignore)
336 // pg is irrelevant for tracking purposes and (at least for the endcaps) is applies to the internal bars only, not to the tubes !!!
337 // =++>>>> IGNORE IT
338 // ep,en: bend the tube by moving (differently) the endplugs ===> the wire straight trajectory is moved w.r.t. the nominal one
339 // in addition the tubes keep their nominal position at the center => the wire is not concentric to
340 // the tube delta_s from ep,en must also be considered for the implementation of the realistic tube
341 // trajectory induced by ep,en
342 // tw,sp,sn,pg (for deltaT and deltaZ) are geometrical effects, that impact on tracking and keep the wire straight.
343 const double chamberHeight = std::max(moduleHeight(), m_reOtherMl->moduleHeight());
344
345
346 // NOTE s0,z0,t0 are the coord. in the amdb frame of this point: the origin of the frame can be different than the fixed point for
347 // deformations s0mdt,z0mdt,t0mdt
348 // (always equal to the point at lowest t,z and s=0 of the MDT stack)
349 ATH_MSG_VERBOSE( "** In "<<__func__<<" - moduleWidthS " << moduleWidthS()<<", moduleWidthL: "
350 <<moduleWidthL() <<", height: "<<chamberHeight<<", thickness: " <<chamberThickness << "." );
351 ATH_MSG_VERBOSE( "** In "<<__func__<<" - going to correct for B-line the position of Point at " << Amg::toString(localTubeEndPoint));
352
353 double s0mdt = localTubeEndPoint.x(); // always I think !
354 if (std::abs(fixedPoint.x()) > 0.01) {
355 s0mdt = localTubeEndPoint.x() - fixedPoint.x();
356 }
357 double z0mdt = localTubeEndPoint.y();
358 // unless in the D section of this station there's a dy diff. from 0 for the innermost MDT multilayer (sometimes
359 // in the barrel)
360 // unless in the D section of this station there's a dz diff. from 0 for the innermost MDT multilayer (often in barrel)
361 if (std::abs(fixedPoint.y()) > 0.01) {
362 z0mdt = localTubeEndPoint.y() - fixedPoint.y();
363 }
364 double t0mdt = localTubeEndPoint.z();
365 if (std::abs(fixedPoint.z()) > 0.01) {
366 t0mdt = localTubeEndPoint.z() - fixedPoint.z();
367 }
368 if (z0mdt < 0 || t0mdt < 0) {
369 ATH_MSG_WARNING(""<<__func__<<": correcting the local position of a point outside the mdt station (2 multilayers) volume -- RE "
370 << idHelperSvc()->toStringDetEl(identify()) << " local point: szt=" <<Amg::toString(localTubeEndPoint)
371 << " fixedPoint " <<Amg::toString(fixedPoint)<<", z0mdt: "<<z0mdt<<", t0mdt"<<t0mdt);
372 }
373 ATH_MSG_VERBOSE( "** In "<<__func__<<" - correct for offset of B-line fixed point " << s0mdt << " " << z0mdt << " " << t0mdt);
374
375 constexpr double amdbMargin = 1.*Gaudi::Units::cm;
376 const double width_actual = moduleWidthS() - amdbMargin + (moduleWidthL() - moduleWidthS()) * (z0mdt / chamberHeight);
377 const double s_rel = s0mdt / (width_actual / 2.);
378 const double z_rel = (z0mdt - chamberHeight / 2.) / (chamberHeight / 2.);
379 const double t_rel = (t0mdt - chamberThickness / 2.) / (chamberThickness / 2.);
380
381 ATH_MSG_VERBOSE( "** In "<<__func__<<" - width_actual: "<<width_actual<<", s_rel: "<<s_rel<<", z_rel: "<<z_rel
382 <<", t_rel:" << t_rel );
383 double ds{0.},dz{0.},dt{0.};
384
385 // sp, sn - cross plate sag out of plane
386 if ( bline.getParameter(Parameter::sp) || bline.getParameter(Parameter::sn)) {
387 double ztmp = z_rel * z_rel - 1;
388 dt += 0.5 * (bline.getParameter(Parameter::sp) + bline.getParameter(Parameter::sn)) * ztmp
389 + 0.5 * (bline.getParameter(Parameter::sp) - bline.getParameter(Parameter::sn)) * ztmp * s_rel;
390 }
391
392 // tw - twist
393 if (bline.getParameter(Parameter::tw)) {
394 dt -= bline.getParameter(Parameter::tw) * s_rel * z_rel;
395 dz += bline.getParameter(Parameter::tw) * s_rel * t_rel * chamberThickness / chamberHeight;
396 ATH_MSG_VERBOSE( "** In "<<__func__<<": tw=" << bline.getParameter(Parameter::tw) << " dt: "<<dt<<", dz: "<< dz );
397 }
398
399 constexpr double expansionScale = BLinePar::expansionScale;
400 // eg - global expansion
401 if (bline.getParameter(Parameter::eg)) {
402 double egppm = bline.getParameter(Parameter::eg) * expansionScale;
403 ds += 0.;
404 dz += z0mdt * egppm;
405 dt += t0mdt * egppm;
406 }
407
408 // ep, en - local expansion
409 //
410 // Imporant note: the chamber height and length, as they denoted in Christoph's talk,
411 // correspond to thickness and height parameters of this function;
412 //
413
414 if (bline.getParameter(Parameter::ep) || bline.getParameter(Parameter::en)) {
415 const double ep = bline.getParameter(Parameter::ep) * expansionScale;
416 const double en = bline.getParameter(Parameter::en) * expansionScale;
417 const double phi = 0.5 * (ep + en) * s_rel * s_rel + 0.5 * (ep - en) * s_rel;
418 const double localDt = phi * (t0mdt - chamberThickness / 2.);
419 const double localDz = phi * (z0mdt - chamberHeight / 2.);
420 dt += localDt;
421 dz += localDz;
422 }
423
424 ATH_MSG_VERBOSE( "posOnDefChamStraighWire: ds="<<ds<<",z="<<dz<<",t="<<dt);
425 deformedPos[0] = localTubeEndPoint[0] + ds;
426 deformedPos[1] = localTubeEndPoint[1] + dz;
427 deformedPos[2] = localTubeEndPoint[2] + dt;
428 return deformedPos;
429}
430#endif
431
432#if defined(FLATTEN)
433 // We compile this package with optimization, even in debug builds; otherwise,
434 // the heavy use of Eigen makes it too slow. However, from here we may call
435 // to out-of-line Eigen code that is linked from other DSOs; in that case,
436 // it would not be optimized. Avoid this by forcing all Eigen code
437 // to be inlined here if possible.
439#endif
441 const ActsTrk::DetectorAlignStore* store) const {
442#ifdef SIMULATIONBASE
443 ATH_MSG_VERBOSE("No deformed transformation available "<<idHelperSvc()->toString(measurementId(tubeHash))
444 <<"store address to make the compiler happy: "<<store);
445 return Amg::Transform3D::Identity();
446#else
448 if (!store || !store->internalAlignment) {
449 ATH_MSG_VERBOSE("No deformed transformation available "<<idHelperSvc()->toString(measurementId(tubeHash)));
450 return Amg::Transform3D::Identity();
451 }
452 using ChamberDistortions = MdtAlignmentStore::chamberDistortions;
453
455 const ChamberDistortions distortPars = static_cast<const MdtAlignmentStore&>(*store->internalAlignment).getDistortion(identify());
456 if (!distortPars) {
457 ATH_MSG_VERBOSE("No set of deformation parameters is in the DB for "<<idHelperSvc()->toString(measurementId(tubeHash)));
458 return Amg::Transform3D::Identity();
459 }
460
461 const Amg::Vector3D fixedPoint{bLineReferencePoint()};
462
463
464 const double height = std::max(moduleHeight(), m_reOtherMl->moduleHeight()) -
465 (tubePitch() - 2. * tubeRadius());
466
467 const Amg::Transform3D toAMDB{asBuiltRefFrame()};
470 const double relSign = (multilayer() == 1 ? -1. : 1.);
471
472 const double modHalfThick{0.5*relSign*moduleThickness()},
473 modHalTHickO{-0.5*relSign*m_reOtherMl->moduleThickness()};
474
475 const double thickness = relSign*( (toAMDB* (modHalfThick*Amg::Vector3D::UnitX())) -
476 (m_reOtherMl->asBuiltRefFrame()*(modHalTHickO* Amg::Vector3D::UnitX()))).z();
477
478
479 Amg::Vector3D idealTube = localTubePos(tubeHash);
481 idealTube[Amg::y] = 0.;
482
483 Amg::Vector3D positiveEnd = toAMDB * (idealTube + 0.5 * uncutTubeLength(tubeHash) * Amg::Vector3D::UnitY());
484 Amg::Vector3D negativeEnd = toAMDB * (idealTube - 0.5 * uncutTubeLength(tubeHash) * Amg::Vector3D::UnitY());
486 if (distortPars.asBuilt) {
487 positiveEnd = wireEndpointAsBuilt(*distortPars.asBuilt, tubeHash, positiveEnd, tubeSide_t::POS);
488 negativeEnd = wireEndpointAsBuilt(*distortPars.asBuilt, tubeHash, negativeEnd, tubeSide_t::NEG);
489 }
490 Amg::Vector3D positiveEndBline{positiveEnd};
491 Amg::Vector3D negativeEndBline{negativeEnd};
492 if (distortPars.bLine) {
493 positiveEndBline = applyBlineCorrections(*distortPars.bLine, positiveEndBline, fixedPoint, thickness);
494 negativeEndBline = applyBlineCorrections(*distortPars.bLine, negativeEndBline, fixedPoint, thickness);
495 }
496
497 ATH_MSG_VERBOSE("Calculate the deformation parameters of "<<idHelperSvc()->toString(measurementId(tubeHash))
498 <<", ideal tube "<<Amg::toString(idealTube)
499 <<", fixed point "<<Amg::toString(fixedPoint)
500 <<"/ "<<Amg::toString(alignableTransform()->getDefTransform() * fixedPoint)
501 <<", thickness: "<<thickness<<", height: "<<height);
502
503 const Amg::Transform3D fromAMDB{toAMDB.inverse()};
505 positiveEnd = fromAMDB * positiveEnd;
506 negativeEnd = fromAMDB * negativeEnd;
507 positiveEndBline = fromAMDB * positiveEndBline;
508 negativeEndBline = fromAMDB * negativeEndBline;
509
510 // Calculate deformation. Make sure that the wire length stays the same.
511 // Code in positionOnDeformedChamber does not provide this by default.
512 // Break transformation into translation of the wire center and the rotation of the wire
513 // Move to the coordinate system originated at the wire center, then rotate the wire, then
514 // move wire center to the new position
515 const Amg::Transform3D to_center{Amg::getTranslate3D(-idealTube)};
516 const Amg::Transform3D from_center{Amg::getTranslate3D( 0.5 * (positiveEndBline + negativeEndBline))};
517 const Amg::Vector3D old_direction = (positiveEnd - negativeEnd).unit();
518 const Amg::Vector3D new_direction = (positiveEndBline - negativeEndBline).unit();
519 const Amg::Vector3D rotation_vector = old_direction.cross(new_direction);
520
521 Amg::Transform3D deformedTransform{Amg::Transform3D::Identity()};
522 if (rotation_vector.mag() > 10. * std::numeric_limits<double>::epsilon()) {
523 const Amg::AngleAxis3D wire_rotation(std::asin(rotation_vector.mag()), rotation_vector.unit());
524 deformedTransform = from_center * wire_rotation * to_center;
525 } else {
526 deformedTransform = from_center * to_center;
527 }
528 ATH_MSG_VERBOSE("To center "<<GeoTrf::toString(to_center)<<" from: "<<GeoTrf::toString(from_center)<<
529 " -- direction: "<<GeoTrf::toString(old_direction)<<" vs. "<<GeoTrf::toString(new_direction)
530 <<" --> rot: "<<GeoTrf::toString(rotation_vector)<<" ==> "<<GeoTrf::toString(deformedTransform,true));
531 return deformedTransform;
532#endif
533}
534
535
536} // namespace MuonGMR4
Scalar phi() const
phi method
Scalar mag() const
mag method
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define AmgSymMatrix(dim)
double tubeLength
#define z
float getParameter(const Parameter p) const
Returns a given parameter.
Definition BLinePar.h:40
static constexpr double expansionScale
Definition BLinePar.h:35
This is a "hash" representation of an Identifier.
Helper struct to cache simulatenously the As-built and the BLine corrections of the Mdts for fast acc...
Container classifier the MDT as-built parameters See parameter description in http://atlas-muon-align...
multilayer_t
MDT multi-layer index.
tubeSide_t
MDT tube side.
double thickness() const override final
Overload from the Acts::DetectorElement (2 * halfheight)
bool isBarrel() const
States whether the chamber is built into the barrel or not.
double moduleWidthL() const
Returns the length of the top edge of the chamber (top width)
Amg::Vector3D highVoltPos(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global position of the High Voltage connectors.
Amg::Vector3D localTubePos(const IdentifierHash &hash) const
Returns the tube position in the chamber coordinate frame (Not applying the B-line corrections)
Amg::Transform3D toTubeFrame(const IdentifierHash &hash) const
Returns the transformation into the rest frame of the tube x-axis: Pointing towards the next layer y-...
static IdentifierHash measurementHash(unsigned int layerNumber, unsigned int tubeNumber)
Transform the layer and tube number to the measurementHash.
Amg::Vector3D bLineReferencePoint() const
Returns the fixed point of the B-line & as-bult defromation model expressed in the as-built frame.
double tubeRadius() const
Adds the thickness of the tube wall onto the radius.
double distanceToReadout(const ActsTrk::GeometryContext &ctx, const Identifier &measId, const Amg::Vector3D &globPoint) const
Returns the distance along the wire from the readout card The distance is given as the delta z of the...
Amg::Vector3D readOutPos(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global position of the readout card.
const MdtIdHelper & m_idHelper
Detector identifier helper to quickly extract the ID fields.
static unsigned int layerNumber(const IdentifierHash &hash)
Transforms the identifier hash into a layer number ranging from (0-numLayers()-1)
double moduleHeight() const
Returns the height of the chamber (Distance bottom - topWidth)
Amg::Transform3D asBuiltRefFrame() const
Returns the transformation to go into the reference frame of the as-buit & b-line model starting from...
Amg::Vector3D globalTubePos(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global position of the tube center.
unsigned int numTubesInLay() const
Returns the number of tubes per layer.
void setComplementaryReadoutEle(const MdtReadoutElement *other)
Set the link to the second readout element inside the muon station.
double moduleThickness() const
Returns the thickness of the chamber.
double moduleWidthS() const
Returns the length of the bottom edge of the chamber (short width)
static unsigned int tubeNumber(const IdentifierHash &hash)
Transforms the idenfier hash into a tube number ranging from (0- numTubesInLay()-1)
double uncutTubeLength(const IdentifierHash &tubeHash) const
Returns the uncut tube length.
Amg::Transform3D fromIdealToDeformed(const IdentifierHash &tubeHash, const ActsTrk::DetectorAlignStore *store) const
Applies the B & as-built parameters.
Amg::Vector3D wireEndpointAsBuilt(const MdtAsBuiltPar &asBuilt, const IdentifierHash &tubeHash, const Amg::Vector3D &nominalEnd, const tubeSide_t side) const
Amg::Vector3D applyBlineCorrections(const BLinePar &bline, const Amg::Vector3D &localTubeEndPoint, const Amg::Vector3D &fixedPoint, const double thickness) const
Apply the B-line model correction to a tube endpoint.
Amg::Transform3D toChamberLayer(const IdentifierHash &hash) const
Returns the transformation into the rest frame of the tube x-axis: Pointing towards the next layer y-...
MdtAsBuiltPar::tubeSide_t tubeSide_t
Moves the wire endpoints according to the as-built model.
unsigned int multilayer() const
Returns the multi layer of the MdtReadoutElement.
Identifier measurementId(const IdentifierHash &measHash) const override final
Converts the measurement hash back to the full Identifier.
double tubePitch() const
Returns the pitch between 2 tubes in a layer.
unsigned int numLayers() const
Returns the number of tube layer.
Helper struct to retrieve the tube lengths and the tube centers directly from the GeoModel tree.
const Amg::Transform3D & layerTransform() const
: Returns the transformation from the layer to the muon station
const Amg::Transform3D tubeTransform(const unsigned int tube) const
Returns the transformation of the tube to the muon station Index counting [0 - nTubes()-1].
double tubeHalfLength(const unsigned int tube) const
Returns the half-length of the given tube.
double uncutHalfLength(const unsigned int tube) const
Returns the uncut-half length of the given tube.
int stationEta() const
Returns the stationEta (positive A site, negative O site)
const Amg::Transform3D & localToGlobalTrans(const ActsTrk::GeometryContext &ctx) const
Returns the local to global transformation into the ATLAS coordinate system.
StatusCode strawSurfaceFactory(const IdentifierHash &hash, std::shared_ptr< const Acts::LineBounds > lBounds)
StatusCode planeSurfaceFactory(const IdentifierHash &hash, std::shared_ptr< const Acts::PlanarBounds > pBounds)
Identifier identify() const override final
Return the athena identifier.
const Muon::IMuonIdHelperSvc * idHelperSvc() const
Returns the pointer to the muonIdHelperSvc.
StatusCode insertTransform(const IdentifierHash &hash)
Inserts a transfomration for caching.
static IdentifierHash geoTransformHash()
Returns the hash that is associated with the surface cache holding the transformation that is placing...
const GeoAlignableTransform * alignableTransform() const
Returnsthe alignable transform of the readout element.
Amg::Transform3D globalToLocalTrans(const ActsTrk::GeometryContext &ctx) const
Transformations to translate between local <-> global coordinates.
#define ATH_FLATTEN
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
Amg::Transform3D getRotateX3D(double angle)
get a rotation transformation around X-axis
Amg::Transform3D getTranslate3D(const double X, const double Y, const double Z)
: Returns a shift transformation along an arbitrary axis
Eigen::AngleAxisd AngleAxis3D
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
The ReadoutGeomCnvAlg converts the Run4 Readout geometry build from the GeoModelXML into the legacy M...
std::ostream & operator<<(std::ostream &ostr, const Chamber::defineArgs &args)
Definition Chamber.cxx:14
GeoModel::TransientConstSharedPtr< MdtTubeLayer > MdtTubeLayerPtr
std::string toString(const MuonGMR4::MuonReadoutElement *re)
STL namespace.
Helper struct to store the pointer to the Mdt distrotion parameters, namely the As-built and the BLin...