ATLAS Offline Software
Loading...
Searching...
No Matches
CscReadoutElement.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <GaudiKernel/IMessageSvc.h>
8#include <GeoModelKernel/GeoDefinitions.h>
9#include <GeoModelKernel/GeoLogVol.h>
10#include <GeoModelKernel/GeoVFullPhysVol.h>
11#include <GeoModelKernel/GeoVPhysVol.h>
12#include <TString.h>
13
14#include <cmath>
15#include <map>
16#include <memory>
17#include <stdexcept>
18#include <utility>
19#include <vector>
20
23#include "GaudiKernel/MsgStream.h"
24#include "GeoModelKernel/GeoFullPhysVol.h"
32
33namespace Trk {
34 class SurfaceBounds;
35}
36
37namespace MuonGM {
38
39 CscReadoutElement::CscReadoutElement(GeoVFullPhysVol* pv, const std::string& stName, MuonDetectorManager* mgr) :
40 MuonClusterReadoutElement(pv, mgr, Trk::DetectorElemType::Csc) {
41 // Set a few parameters here. The rest are set in MuonChamber::setCscReadoutGeometry
42
43
44 // st name
45 setStationName(stName);
46 for (unsigned int i = 0; i < 4; i++) m_wireplanez[i] = 0.;
47
48 if (mgr->MinimalGeoFlag() == 0) {
49 if (GeoFullPhysVol* pvc = dynamic_cast<GeoFullPhysVol*>(pv)) {
50 unsigned int nchildvol = pvc->getNChildVols();
51 int lgg = 0;
52 std::string::size_type npos;
53 for (unsigned ich = 0; ich < nchildvol; ich++) {
54 PVConstLink pc = pvc->getChildVol(ich);
55 std::string childname = (pc->getLogVol())->getName();
56 int nch1 = pc->getNChildVols();
57 lgg = 3;
58 for (int ngv = 0; ngv < nch1; ngv++) {
59 PVConstLink pcgv = pc->getChildVol(ngv);
60 std::string childname1 = (pcgv->getLogVol())->getName();
61
62 if ((npos = childname1.find("CscArCO2")) != std::string::npos) {
63 const GeoTrf::Vector3D trans = (pvc->getXToChildVol(ich) * pc->getXToChildVol(ngv)).translation();
64 m_wireplanez[lgg] = trans.x();
65 lgg--;
66 }
67 }
68 }
69 } else {
70 std::stringstream error_str{};
71 error_str<<__FILE__<<":"<<__LINE__<<" - Cannot performa dynamic cast!";
72 throw std::runtime_error(error_str.str());
73 }
74 } else {
75 // hard wire for the moment
76 double pitch = 25.69;
77 m_wireplanez[0] = -38.51;
78 for (int i = 1; i < 4; ++i) { m_wireplanez[i] = m_wireplanez[i - 1] + pitch; }
79 }
80
81 for (unsigned int i = 0; i < 4; ++i) {
82 for (unsigned int j = 0; j < 3; ++j) {
83 m_cscIntTransl[i][j] = 0.; // first index is wireLayer, second = 0,1,2 for s,z,t
84 }
85 }
86 for (unsigned int i = 0; i < 4; ++i) {
87 for (unsigned int j = 0; j < 3; ++j) {
88 m_cscIntRot[i][j] = 0.; // first index is wireLayer, second = 0,1,2 for rots,z,t
89 }
90 }
91
92 // doTests();
93 }
94
96
98 const Amg::Vector3D gasgapP = localWireLayerPos(id);
99 const Amg::Translation3D xfp(gasgapP.x(), gasgapP.y(), gasgapP.z());
100 return absTransform() * xfp * x;
101 }
102
104 const Amg::Vector3D gasgapP = localWireLayerPos(gasGap);
105 const Amg::Translation3D xfp(gasgapP.x(), gasgapP.y(), gasgapP.z());
106 return absTransform() * xfp;
107 }
109 const Amg::Vector3D gasgapP = localWireLayerPos(id);
110 const Amg::Translation3D xfp(gasgapP.x(), gasgapP.y(), gasgapP.z());
111 return absTransform() * xfp;
112 }
113
115 return localToGlobalTransf(id).inverse() * x;
116 }
117
119
121 const CscIdHelper* idh = manager()->cscIdHelper();
122 int gasgap = idh->wireLayer(id);
123 return localWireLayerPos(gasgap);
124 }
125
127 Amg::Vector3D localP(m_wireplanez[gg - 1], 0., 0.);
128 return localP;
129 }
130
132 const CscIdHelper* idh = manager()->cscIdHelper();
133 int gasgap = idh->wireLayer(id);
134 return wireLayerPos(gasgap);
135 }
136
138 const Amg::Vector3D localP = localWireLayerPos(gg);
139 const Amg::Transform3D cscTrans = absTransform();
140#ifndef NDEBUG
141 MsgStream log(Athena::getMessageSvc(), "CscReadoutElement");
142 if (log.level() <= MSG::VERBOSE) log << "CscReadoutElement::wireLayerPos got localWireLayerPos " << localP << endmsg;
143#endif
144 return cscTrans * localP;
145 }
146
147 double CscReadoutElement::cathodeReadoutPitch(int /*chLayer*/, int measuresPhi) const {
148 if (measuresPhi == 0)
149 return m_Etastrippitch;
150 else
151 return m_Phistrippitch;
152 }
154 if (measuresPhi == 0)
155 return m_Etastrippitch;
156 else
157 return m_Phistrippitch;
158 }
159
161
163 if (measuresPhi == 0)
165 else
167 }
168
170 double midWidth = 0;
171 // we need to know the geometry version
172 // if P or earlier, we have pointing phi strips
173 // if Q or later, we have parallel phi strips
174 // R-strips are alwas parallel in all the geometry layouts
175
176 if (0 == measuresPhi) {
177 midWidth = length() - 2. * roxacellWidth();
178 } else {
179 double beta = std::atan((longWidth() - shortWidth()) / (2. * lengthUpToMaxWidth()));
180 double lWidth = longWidth() - 2 * roxacellWidth() * (1 + std::sin(beta)) / std::cos(beta);
181 midWidth = lWidth;
182 }
183
184 return midWidth;
185 }
186
187 double CscReadoutElement::z0() const {
188 double beta = std::atan((longWidth() - shortWidth()) / (2. * lengthUpToMaxWidth()));
189 double sWidth = shortWidth() - 2 * roxacellWidth() * (1 - std::sin(beta)) / std::cos(beta);
190 double lWidth = longWidth() - 2 * roxacellWidth() * (1 + std::sin(beta)) / std::cos(beta);
191 if (lengthUpToMaxWidth() == length()) {
192 double realLength = lengthUpToMaxWidth() - 2 * roxacellWidth();
193 return (realLength * sWidth / (lWidth - sWidth));
194 } else {
195 double bigLength = length() - 2 * roxacellWidth();
196 double alpha = std::atan((excent() - lengthUpToMaxWidth()) / (longWidth() / 2.));
197 double shortLongWidth = longWidth() * (excent() - length()) / (excent() - lengthUpToMaxWidth());
198 double gslWidth = shortLongWidth - 2 * roxacellWidth() * (1 - std::cos(alpha)) / std::sin(alpha);
199 lWidth = 2 * (bigLength + 0.5 * sWidth / std::tan(beta) + 0.5 * gslWidth * std::tan(alpha)) /
200 (std::tan(alpha) + 1.0 / std::tan(beta));
201 double shortLength = bigLength - (lWidth - gslWidth) * std::tan(alpha) / 2.;
202 return (shortLength * sWidth / (lWidth - sWidth));
203 }
204 }
205
207 // uses localStripPos(int chamberLayer, int wireLayer, int measPhi, int channel) const;
208 const CscIdHelper* idh = manager()->cscIdHelper();
209 int eta = idh->stationEta(id);
210 int chamberLayer = idh->chamberLayer(id);
211 int wireLayer = idh->wireLayer(id);
212 int measPhi = idh->measuresPhi(id);
213 int channel = idh->strip(id);
214 return localStripPos(eta, chamberLayer, wireLayer, measPhi, channel);
215 }
217 // uses localStripPos(int chamberLayer, int wireLayer, int measPhi, int channel) const;
218 const CscIdHelper* idh = manager()->cscIdHelper();
219 int eta = idh->stationEta(id);
220 int chamberLayer = idh->chamberLayer(id);
221 int wireLayer = idh->wireLayer(id);
222 int measPhi = idh->measuresPhi(id);
223 int channel = idh->strip(id);
224 return nominalLocalStripPos(eta, chamberLayer, wireLayer, measPhi, channel);
225 }
226
228 const CscIdHelper* idh = manager()->cscIdHelper();
229 int eta = idh->stationEta(id);
230 int chamberLayer = idh->chamberLayer(id);
231 int wireLayer = idh->wireLayer(id);
232 int measPhi = idh->measuresPhi(id);
233 int channel = idh->strip(id);
234 return stripPos(eta, chamberLayer, wireLayer, measPhi, channel);
235 }
237 const CscIdHelper* idh = manager()->cscIdHelper();
238 int eta = idh->stationEta(id);
239 int chamberLayer = idh->chamberLayer(id);
240 int wireLayer = idh->wireLayer(id);
241 int measPhi = idh->measuresPhi(id);
242 int channel = idh->strip(id);
243 return nominalStripPos(eta, chamberLayer, wireLayer, measPhi, channel);
244 }
245
246 Amg::Vector3D CscReadoutElement::stripPos(int eta, int chamberLayer, int wireLayer, int measPhi, int channel) const {
247 // const Amg::Vector3D localP = nominalLocalStripPos(eta, chamberLayer, wireLayer,
248 // measPhi, channel);
249 const Amg::Vector3D localP = localStripPos(eta, chamberLayer, wireLayer, measPhi, channel);
250 const Amg::Transform3D cscTrans = absTransform();
251 return cscTrans * localP;
252 }
253
254 Amg::Vector3D CscReadoutElement::nominalStripPos(int eta, int chamberLayer, int wireLayer, int measPhi, int channel) const {
255 const Amg::Vector3D localP = nominalLocalStripPos(eta, chamberLayer, wireLayer, measPhi, channel);
256 const Amg::Transform3D cscTrans = absTransform();
257 return cscTrans * localP;
258 }
259
260 double CscReadoutElement::StripWidth(int chlayer, int measphi) const {
261 // assume StripWidth = StripPitch
262 double width = cathodeReadoutPitch(chlayer, measphi);
263 return width;
264 }
265 double CscReadoutElement::StripPitch(int chlayer, int measphi) const {
266 // assume StripWidth = StripPitch
267 double width = cathodeReadoutPitch(chlayer, measphi);
268 return width;
269 }
270 double CscReadoutElement::StripWidth(int measphi) const {
271 // assume StripWidth = StripPitch
272 double width = cathodeReadoutPitch(measphi);
273 return width;
274 }
275 double CscReadoutElement::StripPitch(int measphi) const {
276 // assume StripWidth = StripPitch
277 double width = cathodeReadoutPitch(measphi);
278 return width;
279 }
280
281 //****************************************************************************
283 const CscIdHelper* idh = manager()->cscIdHelper();
284 int chamberLayer = idh->chamberLayer(id);
285 int measPhi = idh->measuresPhi(id);
286 int channel = idh->strip(id);
287 double epsilon;
288 return stripLength(chamberLayer, measPhi, channel, epsilon);
289 }
290
291 //****************************************************************************
292 double CscReadoutElement::stripLength(int chamberLayer, int measuresPhi, int stripNumber, double& epsilon) const {
293 double stripWidth = cathodeReadoutPitch(chamberLayer, measuresPhi);
295
296 double chamberLength = length() - 2 * roxacellWidth();
297 double beta = std::atan((longWidth() - shortWidth()) / (2. * lengthUpToMaxWidth()));
298
299 double smallWidth = shortWidth() - 2 * roxacellWidth() * (1.0 - std::sin(beta)) / std::cos(beta);
300 double bigWidth = longWidth() - 2 * roxacellWidth() * (1.0 + std::sin(beta)) / std::cos(beta);
301 double gslWidth{0.}, sLength{0.};
302
303 double alpha = std::atan((excent() - lengthUpToMaxWidth()) / (longWidth() / 2.));
304 if (length() != lengthUpToMaxWidth()) {
305 double shortLongWidth = longWidth() * (excent() - length()) / (excent() - lengthUpToMaxWidth());
306 gslWidth = shortLongWidth - 2 * roxacellWidth() * (1 - std::cos(alpha)) / std::sin(alpha);
307 bigWidth = 2 * (chamberLength + 0.5 * smallWidth / std::tan(beta) + 0.5 * gslWidth * std::tan(alpha)) /
308 (std::tan(alpha) + 1.0 / std::tan(beta));
309 }
310
311 double pos = stripWidth * (stripNumber - 0.5 - numberOfStrips / 2.0);
312 epsilon = lengthCorrection(measuresPhi, pos);
313 double stripPos = std::abs(pos);
314
315 if (measuresPhi == 0) {
316 double effectiveLength = stripWidth * numberOfStrips;
317 sLength = 2.0 * (effectiveLength / 2.0 + pos) * std::tan(beta) + smallWidth;
318 } else {
319 if (stripPos <= (smallWidth / 2.0))
320 sLength = chamberLength;
321 else {
322 double diff = stripPos - smallWidth / 2.0;
323 if (length() != lengthUpToMaxWidth()) {
324 double shortLength = chamberLength - (bigWidth - gslWidth) * std::tan(alpha) / 2.;
325 sLength = chamberLength - 2.0 * diff * shortLength / (bigWidth - smallWidth);
326 } else
327 sLength = chamberLength * (1.0 - 2.0 * diff / (bigWidth - smallWidth));
328 }
329 }
330 return (sLength - epsilon);
331 }
332
334 if (lengthUpToMaxWidth() == length()) return 0.0; // CSS
335
336 double epsilon = 0.0;
337 double alpha = std::atan((excent() - lengthUpToMaxWidth()) / (longWidth() / 2.));
338 double beta = std::atan((longWidth() - shortWidth()) / (2. * lengthUpToMaxWidth()));
339
340 double bigLength = length() - 2 * roxacellWidth();
341 double shortLongWidth = longWidth() * (excent() - length()) / (excent() - lengthUpToMaxWidth());
342 double gslWidth = shortLongWidth - 2 * roxacellWidth() * (1 - std::cos(alpha)) / std::sin(alpha);
343 double smallWidth = shortWidth() - 2 * roxacellWidth() * (1 - std::sin(beta)) / std::cos(beta);
344 double bigWidth = 2 * (bigLength + 0.5 * smallWidth / std::tan(beta) + 0.5 * gslWidth * std::tan(alpha)) /
345 (std::tan(alpha) + 1.0 / std::tan(beta));
346 double shortLength = bigLength - (bigWidth - gslWidth) * std::tan(alpha) / 2.;
347
348 if (measuresPhi == 1) {
349 if (std::abs(stripPos) > (gslWidth / 2.)) epsilon = (std::abs(stripPos) - gslWidth / 2.) * std::tan(alpha);
350 } else {
351 double z0 = shortLength - bigLength / 2;
352 if (stripPos > z0) {
353 double diff = stripPos - z0;
354 double corr1 = diff / std::tan(alpha);
355 double corr2 = diff * std::tan(beta);
356 epsilon = 2.0 * (corr1 + corr2);
357 }
358 }
359 if (epsilon < 0.0) epsilon = 0.0;
360 return epsilon;
361 }
362
363 //****************************************************************************
364 Amg::Vector3D CscReadoutElement::localStripPos(int eta, int chamberLayer, int wireLayer, int measPhi, int strip) const {
365 Amg::Vector3D nominalLP = nominalLocalStripPos(eta, chamberLayer, wireLayer, measPhi, strip);
366 // const Amg::Transform3D cscTrans = absTransform();
367 Amg::Transform3D transfPtr_internalgeo(
368 Amg::Translation3D(m_cscIntTransl[wireLayer - 1][2], m_cscIntTransl[wireLayer - 1][0], m_cscIntTransl[wireLayer - 1][1]) *
369 Amg::AngleAxis3D(m_cscIntRot[wireLayer - 1][0], Amg::Vector3D::UnitY()) *
370 Amg::AngleAxis3D(m_cscIntRot[wireLayer - 1][1], Amg::Vector3D::UnitZ()) *
371 Amg::AngleAxis3D(m_cscIntRot[wireLayer - 1][2], Amg::Vector3D::UnitX()));
372 return transfPtr_internalgeo * nominalLP;
373 }
374 //****************************************************************************
375 Amg::Vector3D CscReadoutElement::nominalLocalStripPos(int eta, int chamberLayer, int wireLayer, int measPhi, int strip) const {
376 // get the coordinate of the strip plane
377 Amg::Vector3D stripPlane = localStripLayerPos(chamberLayer, wireLayer, measPhi, strip);
378
379 // some initializations
380 double x = stripPlane.x();
381 double y = stripPlane.y();
382 double z = stripPlane.z();
383
384 // we need to know the geometry version
385 // if P or earlier, we have pointing phi strips
386 // if Q or later, we have parallel phi strips
387 // R-strips are alwas parallel in all the geometry layouts
388
389 double epsilon = 0.0;
390 double lengthOfStrip = stripLength(chamberLayer, measPhi, strip, epsilon);
391
392 // get some necessary parameters
393 double stripWidth = cathodeReadoutPitch(chamberLayer, measPhi);
394 int nStrips = maxNumberOfStrips(measPhi, stripWidth);
395
396 if (0 == measPhi) {
397 z = stripWidth * (strip - 0.5 - nStrips / 2.0);
398 } else {
399 z = (length() - 2 * roxacellWidth() - lengthOfStrip) / 2.0 - epsilon;
400 if (eta < 0)
401 y = stripWidth * (strip - 0.5 - nStrips / 2.0);
402 else
403 y = -stripWidth * (strip - 0.5 - nStrips / 2.0);
404 }
405
406 return Amg::Vector3D(x, y, z);
407 }
408
409 //****************************************************************************
410 Amg::Vector3D CscReadoutElement::nominalLocalClusterPos(int eta, int wireLayer, int measPhi, double p) const {
411 // get the coordinates of the wire plane
412 Amg::Vector3D wireLayerPosition = localWireLayerPos(wireLayer);
413
414 // some initializations
415 double x = wireLayerPosition.x();
416 double y = wireLayerPosition.y();
417 double z = wireLayerPosition.z();
418
419 // local position of cluster
420 if (0 == measPhi)
421 z = p;
422 else {
423 if (eta < 0)
424 y = p;
425 else
426 y = -p;
427 }
428 return Amg::Vector3D(x, y, z);
429 }
430
431 //****************************************************************************
432 Amg::Vector3D CscReadoutElement::localClusterPos(int eta, int wireLayer, int measPhi, double p) const {
433 Amg::Vector3D nominalLCP = nominalLocalClusterPos(eta, wireLayer, measPhi, p);
434
435 Amg::Transform3D transfPtr_internalgeo = Amg::Transform3D::Identity();
436 transfPtr_internalgeo *=
437 Amg::Translation3D(m_cscIntTransl[wireLayer - 1][2], m_cscIntTransl[wireLayer - 1][0], m_cscIntTransl[wireLayer - 1][1]);
438 transfPtr_internalgeo *= Amg::AngleAxis3D(m_cscIntRot[wireLayer - 1][0], Amg::Vector3D::UnitY());
439 transfPtr_internalgeo *= Amg::AngleAxis3D(m_cscIntRot[wireLayer - 1][1], Amg::Vector3D::UnitZ());
440 transfPtr_internalgeo *= Amg::AngleAxis3D(m_cscIntRot[wireLayer - 1][2], Amg::Vector3D::UnitX());
441
442 return transfPtr_internalgeo * nominalLCP;
443 }
444
445 //****************************************************************************
447 // localP is a local position
448 const Amg::Transform3D cscTrans = absTransform();
449 return cscTrans.inverse() * globalP;
450 }
451
452 //****************************************************************************
454 // globalP is a global position
455 const Amg::Transform3D cscTrans = absTransform();
456 return cscTrans * localP;
457 }
458
459 //****************************************************************************
461
463 const CscIdHelper* idh = manager()->cscIdHelper();
464 int eta = idh->stationEta(id);
465 int chamberLayer = idh->chamberLayer(id);
466 bool measPhi = idh->measuresPhi(id);
467 int strip = idh->strip(id);
468 // get some necessary parameters
469 double stripWidth = cathodeReadoutPitch(chamberLayer, measPhi);
470 int nStrips = maxNumberOfStrips(measPhi, stripWidth);
471 double pos = stripWidth * (strip - 0.5 - nStrips / 2.0);
472 if (eta > 0 && measPhi) pos *= -1;
473 return pos;
474 }
475
476 //****************************************************************************
477 Amg::Vector3D CscReadoutElement::localStripLayerPos(int /*chamberLayer*/, int wireLayer, int measPhi, int /*strip*/) const {
478 if (measPhi != 0 && measPhi != 1) throw std::runtime_error ("CscReadoutElement::localStripLayerPos bad measPhi");
479 Amg::Vector3D wireLayerPosition = localWireLayerPos(wireLayer);
480 double anodeCathodeDis = anodeCathodeDistance();
481 double x = wireLayerPosition.x();
482 double y = wireLayerPosition.y();
483 double z = wireLayerPosition.z();
484
485 if (wireLayer == 1 || wireLayer == 3) {
486 if (measPhi == 0)
487 x = wireLayerPosition.x() + anodeCathodeDis;
488 else
489 x = wireLayerPosition.x() - anodeCathodeDis;
490 } else {
491 if (measPhi == 0)
492 x = wireLayerPosition.x() - anodeCathodeDis;
493 else
494 x = wireLayerPosition.x() + anodeCathodeDis;
495 }
496
497 return Amg::Vector3D(x, y, z);
498 }
499
500 // ******************************* sin stereo*************************************
501 double CscReadoutElement::sinStereo(const Identifier& id) const {
502 // sin stero for R-strips
503 Amg::Vector3D posStrip = stripPos(id);
504 const CscIdHelper* idh = manager()->cscIdHelper();
505 int measPhi = idh->measuresPhi(id);
506 if (measPhi == 0) return 1.0;
507
508 // return zero for phi strips in layout P
509 // std::string gVersion = manager()->geometryVersion();
510
511 // sin stero for phi strips in layout Q and above
512 int eta = idh->stationEta(id);
513 int chamberLayer = idh->chamberLayer(id);
514 int wireLayer = idh->wireLayer(id);
515 int strip = maxNumberOfStrips(measPhi) / 2;
516 Amg::Vector3D etaAxis = stripPos(eta, chamberLayer, wireLayer, measPhi, strip);
517 double sinstero = (posStrip.y() * etaAxis.x() - posStrip.x() * etaAxis.y()) / (posStrip.perp() * etaAxis.perp());
518 return sinstero;
519 }
520
522#ifndef NDEBUG
523 MsgStream log(Athena::getMessageSvc(), "CscReadoutElement");
524 if (log.level() <= MSG::VERBOSE) {
525 constexpr std::array<int, 2> eta{1, -1};
526 constexpr std::array<int, 2> maxStrips{192, 48};
527 int chamberLayer = 1;
528 int wireLayer = 4;
529 for (int measPhi = 0; measPhi < 2; ++measPhi) {
530 for (int ieta = 0; ieta < 2; ++ieta) {
531 for (int ilayer = 1; ilayer <= wireLayer; ++ilayer) {
532 int strips[3] = {1, maxStrips[measPhi] / 2, maxStrips[measPhi]};
533 for (int i = 0; i < 3; i++) {
534 int istrip = strips[i];
535 Amg::Vector3D npos = nominalLocalStripPos(eta[ieta], chamberLayer, ilayer, measPhi, istrip);
536 Amg::Vector3D pos = localStripPos(eta[ieta], chamberLayer, ilayer, measPhi, istrip);
537 log << MSG::VERBOSE << "the nominal positions = " << npos.x() << " " << npos.y() << " " << npos.z() << endmsg;
538 log << MSG::VERBOSE << "the positions = " << pos.x() << " " << pos.y() << " " << pos.z() << endmsg;
539 }
540 }
541 }
542 }
543 }
544#endif
545 }
546
548 const CscIdHelper* idh = manager()->cscIdHelper();
549 int chamberLayer = idh->chamberLayer(id);
550 int wireLayer = idh->wireLayer(id);
551 int measuresPhi = idh->measuresPhi(id);
552 int strip = idh->strip(id);
553 return stripLayerPos(chamberLayer, wireLayer, measuresPhi, strip);
554 }
555
557 Identifier id;
558 const CscIdHelper* idh = manager()->cscIdHelper();
559 IdContext context = idh->channel_context();
560 if (!idh->get_id(hash, id, &context))
561 return stripLayerPos(id);
562 else
563 return Amg::Vector3D(0, 0, 0);
564 }
565
566 Amg::Vector3D CscReadoutElement::stripLayerPos(int chamberLayer, int wireLayer, int measPhi, int channel) const {
567 Amg::Vector3D localP = localStripLayerPos(chamberLayer, wireLayer, measPhi, channel);
568 const Amg::Transform3D cscTrans = absTransform();
569 return cscTrans * localP;
570 }
571
573 // get id helper
574 const CscIdHelper& idh{idHelperSvc()->cscIdHelper()};
575 const int wlayer = idh.wireLayer(x.identify());
576 const bool notAllowedLayer = (wlayer > 4 || wlayer <1);
577
578
579 if (idh.elementID(x.identify()) != idh.elementID(identify()) || notAllowedLayer) {
580 ATH_MSG_WARNING("Trying to set the following CSC internal A-line " << x << " for Csc readout Element " << idHelperSvc()->toString(identify())
581 << "Inconsistent CSC int. Aline assignment - Internal alignment will not be applied ");
582 return;
583 }
584 ATH_MSG_DEBUG("Set internal alignment parameter "<<x);
585 using Parameter = ALinePar::Parameter;
586 m_cscIntTransl[wlayer - 1][0] = x.getParameter(Parameter::transS);
587 m_cscIntTransl[wlayer - 1][1] = x.getParameter(Parameter::transZ);
588 m_cscIntTransl[wlayer - 1][2] = x.getParameter(Parameter::transT);
589 m_cscIntRot[wlayer - 1][0] =x.getParameter(Parameter::rotS);
590 m_cscIntRot[wlayer - 1][1] =x.getParameter(Parameter::rotZ);
591 m_cscIntRot[wlayer - 1][2] =x.getParameter(Parameter::rotT);
592
593 for (unsigned int j = 0; j < 3; ++j) {
594 ATH_MSG_DEBUG("<CscReadoutElement::setCscInternalAlignmentPar()>: m_cscIntTransl[" << (wlayer - 1) << "][" << j
595 << "]: " << m_cscIntTransl[(wlayer - 1)][j]);
596 ATH_MSG_DEBUG("<CscReadoutElement::setCscInternalAlignmentPar()>: m_cscIntRot[" << (wlayer - 1) << "][" << j
597 << "]: " << m_cscIntRot[(wlayer - 1)][j]);
598 }
599 }
600
601
602 double CscReadoutElement::getGasGapIntAlign_s(int gasGap) const { return m_cscIntTransl[gasGap - 1][0]; }
603
604 double CscReadoutElement::getGasGapIntAlign_z(int gasGap) const { return m_cscIntTransl[gasGap - 1][1]; }
605
606 double CscReadoutElement::getGasGapIntAlign_t(int gasGap) const { return m_cscIntTransl[gasGap - 1][2]; }
607
608 double CscReadoutElement::getGasGapIntAlign_rots(int gasGap) const { return m_cscIntRot[gasGap - 1][0]; }
609
610 double CscReadoutElement::getGasGapIntAlign_rotz(int gasGap) const { return m_cscIntRot[gasGap - 1][1]; }
611
612 double CscReadoutElement::getGasGapIntAlign_rott(int gasGap) const { return m_cscIntRot[gasGap - 1][2]; }
613
615 const CscIdHelper* idh = manager()->cscIdHelper();
616 return nominalTransform(idh->wireLayer(id), idh->measuresPhi(id));
617 }
619 Amg::RotationMatrix3D muonTRotation(localToGlobalTransf(gasGap).rotation());
620 Amg::RotationMatrix3D surfaceTRotation;
621 surfaceTRotation.col(0) = muonTRotation.col(1);
622 surfaceTRotation.col(1) = muonTRotation.col(2);
623 surfaceTRotation.col(2) = muonTRotation.col(0);
624 if (measPhi == 0) surfaceTRotation = surfaceTRotation * Amg::AngleAxis3D(M_PI / 2., Amg::Vector3D::UnitZ());
625
626 Amg::Transform3D transfPtr_orig(surfaceTRotation);
627 transfPtr_orig *= Amg::Translation3D(localToGlobalTransf(gasGap).translation());
628#ifndef NDEBUG
629 MsgStream log(Athena::getMessageSvc(), "CscReadoutElement");
630 if (log.level() <= MSG::DEBUG) {
631 log << MSG::DEBUG << "nominalTransform+++++++++++Original Tranformation ++++++++++++++++++++++" << endmsg;
632 log << MSG::DEBUG << (transfPtr_orig)(0, 0) << " " << (transfPtr_orig)(0, 1) << " " << (transfPtr_orig)(0, 2) << " "
633 << (transfPtr_orig)(0, 3) << endmsg;
634 log << MSG::DEBUG << (transfPtr_orig)(1, 0) << " " << (transfPtr_orig)(1, 1) << " " << (transfPtr_orig)(1, 2) << " "
635 << (transfPtr_orig)(1, 3) << endmsg;
636 log << MSG::DEBUG << (transfPtr_orig)(2, 0) << " " << (transfPtr_orig)(2, 1) << " " << (transfPtr_orig)(2, 2) << " "
637 << (transfPtr_orig)(2, 3) << endmsg;
638 log << MSG::DEBUG << "+++++ transf ends " << endmsg;
639 }
640#endif
641 return transfPtr_orig;
642 }
644 const CscIdHelper* idh = manager()->cscIdHelper();
645 return stripPosOnTrackingSurface(idh->stationEta(id), idh->chamberLayer(id), idh->wireLayer(id), idh->measuresPhi(id),
646 idh->strip(id));
647 }
648 Amg::Vector3D CscReadoutElement::stripPosOnTrackingSurface(int eta, int chamberLayer, int wireLayer, int measPhi, int channel) const {
649 Amg::Vector3D nP = nominalLocalStripPos(eta, chamberLayer, wireLayer, measPhi, channel);
650
651 if (measPhi == 1)
652 return Amg::Vector3D(nP.y(), 0., 0.);
653 else
654 return Amg::Vector3D(nP.z(), 0., 0.);
655 }
656 Amg::Vector3D CscReadoutElement::nominalCenter(int gasGap) const { return nominalTransform(gasGap, 1) * Amg::Vector3D(0., 0., 0.); }
658
660 if (!m_surfaceData)
661 m_surfaceData = std::make_unique<SurfaceData>();
662 else {
663 MsgStream log(Athena::getMessageSvc(), "CscReadoutElement");
664 if (log.level() <= MSG::WARNING) log << MSG::WARNING << "calling fillCache on an already filled cache" << endmsg;
665 return;
666 }
667 const CscIdHelper* idh = manager()->cscIdHelper();
668 Identifier parentID = idh->parentID(identify());
669
670 // loop over all gas gaps
671 for (int gp = 1; gp <= m_ngasgaps; ++gp) {
672 // loop over phi/eta projections
673 for (int mp = 1; mp >= 0; --mp) {
674 Identifier id = idh->channelID(parentID, ChamberLayer(), gp, mp, 1);
675
676 const Amg::Vector3D gasgapP = localWireLayerPos(gp);
677 const Amg::Translation3D xfp(gasgapP.x(), gasgapP.y(), gasgapP.z());
678 Amg::Transform3D trans3D = absTransform() * xfp;
679 Amg::RotationMatrix3D muonTRotation(trans3D.rotation());
680 Amg::RotationMatrix3D surfaceTRotation;
681 surfaceTRotation.col(0) = muonTRotation.col(1);
682 surfaceTRotation.col(1) = muonTRotation.col(2);
683 surfaceTRotation.col(2) = muonTRotation.col(0);
684 if (mp == 0) surfaceTRotation = surfaceTRotation * Amg::AngleAxis3D(M_PI / 2., Amg::Vector3D::UnitZ());
685
686 Amg::Transform3D transfPtr_orig(surfaceTRotation);
687 transfPtr_orig.pretranslate(trans3D.translation());
688 Amg::Transform3D transfPtr_internalgeo{Amg::Transform3D::Identity()};
689 if (mp == 1) {
690 transfPtr_internalgeo *=
691 Amg::Translation3D(m_cscIntTransl[gp - 1][0], m_cscIntTransl[gp - 1][1], m_cscIntTransl[gp - 1][2]);
692 transfPtr_internalgeo *= Amg::AngleAxis3D(m_cscIntRot[gp - 1][0], Amg::Vector3D::UnitX());
693 transfPtr_internalgeo *= Amg::AngleAxis3D(m_cscIntRot[gp - 1][1], Amg::Vector3D::UnitY());
694 transfPtr_internalgeo *= Amg::AngleAxis3D(m_cscIntRot[gp - 1][2], Amg::Vector3D::UnitZ());
695 } else {
696 transfPtr_internalgeo *=
697 Amg::Translation3D(m_cscIntTransl[gp - 1][1], -m_cscIntTransl[gp - 1][0], m_cscIntTransl[gp - 1][2]);
698 transfPtr_internalgeo *= Amg::AngleAxis3D(-m_cscIntRot[gp - 1][0], Amg::Vector3D::UnitY());
699 transfPtr_internalgeo *= Amg::AngleAxis3D(m_cscIntRot[gp - 1][1], Amg::Vector3D::UnitX());
700 transfPtr_internalgeo *= Amg::AngleAxis3D(m_cscIntRot[gp - 1][2], Amg::Vector3D::UnitZ());
701 }
702
703 m_surfaceData->m_layerTransforms.push_back(Amg::Transform3D(transfPtr_orig * transfPtr_internalgeo));
704 m_surfaceData->m_layerSurfaces.emplace_back(std::make_unique<Trk::PlaneSurface>(*this, id));
705 if (mp == 1) {
706 m_surfaceData->m_layerCenters.push_back(m_surfaceData->m_layerTransforms.back() * Amg::Vector3D(0., 0., 0.));
707 m_surfaceData->m_layerNormals.emplace_back(m_surfaceData->m_layerTransforms.back().linear() * Amg::Vector3D::UnitZ());
708 }
709 }
710 }
711
712 m_surfaceData->m_surfBounds.emplace_back(
713 std::make_unique<Trk::TrapezoidBounds>(m_Ssize / 2., m_LongSsize / 2., m_Rsize / 2.)); // phi measurement
714 m_surfaceData->m_surfBounds.emplace_back(
715 std::make_unique<Trk::RotatedTrapezoidBounds>(m_Rsize / 2., m_Ssize / 2., m_LongSsize / 2.)); // eta measurement
716 }
717
719 const CscIdHelper* idh = manager()->cscIdHelper();
720
721 int chamberLayer = idh->chamberLayer(id);
722 if (chamberLayer != ChamberLayer()) return false;
723
724 int wireLayer = idh->wireLayer(id);
725 if (wireLayer < 1 || wireLayer > Ngasgaps()) return false;
726
727 int measPhi = idh->measuresPhi(id);
728 int channel = idh->strip(id);
729 if (measPhi == 0) {
730 if (channel < 1 || channel > NetaStrips(wireLayer)) return false;
731 } else if (measPhi == 1) {
732 if (channel < 1 || channel > NphiStrips(wireLayer)) return false;
733 } else
734 return false;
735
736 return true;
737 }
738
740 MsgStream log(Athena::getMessageSvc(), "CscReadoutElement");
741 if (log.level() <= MSG::WARNING) log << MSG::WARNING << " distanceToReadout::dummy routine " << endmsg;
742 return 0.;
743 }
744
746 MsgStream log(Athena::getMessageSvc(), "CscReadoutElement");
747 if (log.level() <= MSG::WARNING) log << MSG::WARNING << " stripNumber::dummy routine " << endmsg;
748 return 1;
749 }
750
753 Amg::Vector3D gpos = stripPos(id);
754 if (!surface(id).globalToLocal(gpos, gpos, pos)) {
755 MsgStream log(Athena::getMessageSvc(), "CscReadoutElement");
756 if (log.level() <= MSG::WARNING)
757 log << MSG::WARNING << " stripPosition:: globalToLocal failed " << surface(id).transform().inverse() * gpos << endmsg;
758 return false;
759 }
760 return true;
761 }
762
763 bool CscReadoutElement::spacePointPosition(const Identifier& phiId, const Identifier& etaId, Amg::Vector2D& pos) const {
764 Amg::Vector2D phiPos;
765 Amg::Vector2D etaPos;
766 if (!stripPosition(phiId, phiPos) || !stripPosition(etaId, etaPos)) return false;
767 spacePointPosition(phiPos, etaPos, pos);
768 return true;
769 }
770
771} // namespace MuonGM
#define M_PI
Scalar eta() const
pseudorapidity method
#define endmsg
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
Definition Jet.cxx:631
const double width
#define y
#define x
#define z
Parameter
amdb frame (s, z, t) = chamber frame (y, z, x)
Definition ALinePar.h:23
Identifier parentID(const Identifier &id) const
get parent id from channel id
Identifier channelID(int stationName, int stationEta, int stationPhi, int chamberLayer, int wireLayer, int measuresPhi, int strip) const
Identifier elementID(int stationName, int stationEta, int stationPhi) const
int wireLayer(const Identifier &id) const
int chamberLayer(const Identifier &id) const
int strip(const Identifier &id) const
bool measuresPhi(const Identifier &id) const override
This class saves the "context" of an expanded identifier (ExpandedIdentifier) for compact or hash ver...
Definition IdContext.h:26
This is a "hash" representation of an Identifier.
Amg::Vector3D localClusterPos(int eta, int wireLayer, int measPhi, double x0) const
takes into account internal alignment parameters, hence gives generally answer (local here is the sta...
virtual bool stripPosition(const Identifier &id, Amg::Vector2D &pos) const override final
strip position If the strip number is outside the range of valid strips, the function will return fal...
Amg::Vector3D localStripPos(const Identifier &id) const
takes into account internal alignment parameters, hence gives generally accurate answer (local here i...
double stripLength(int chamberLayer, int measuresPhi, int stripNumber, double &epsilon) const
std::array< double, maxwlay > m_wireplanez
Amg::Vector3D nominalLocalStripPos(const Identifier &id) const
ignores internal alignment parameters, hence gives generally incorrect answer (local here is the stat...
double getGasGapIntAlign_t(int gasGap) const
double StripPitch(int chlayer, int measphi) const
double StripWidth(int chlayer, int measphi) const
double cathodeReadoutPitch(int chLayer, int measuresPhi) const
virtual bool measuresPhi(const Identifier &id) const override final
returns whether the given identifier measures phi or not
Amg::Vector3D nominalLocalClusterPos(int eta, int wireLayer, int measPhi, double x0) const
ignores internal alignment parameters, hence gives generally incorrect answer (local here is the stat...
virtual int stripNumber(const Amg::Vector2D &pos, const Identifier &id) const override final
strip number corresponding to local position.
Amg::Vector3D wireLayerPos(const Identifier &id) const
double getGasGapIntAlign_rots(int gasGap) const
double getGasGapIntAlign_rotz(int gasGap) const
double getGasGapIntAlign_z(int gasGap) const
virtual bool spacePointPosition(const Identifier &phiId, const Identifier &etaId, Amg::Vector2D &pos) const override
space point position for a given pair of phi and eta identifiers The LocalPosition is expressed in th...
Amg::Vector3D globalToLocalCoords(const Amg::Vector3D &x, const Identifier &id) const
double activeWidth(int measuresPhi) const
double sinStereo(const Identifier &stripId) const
Amg::Vector3D globalPos(const Amg::Vector3D &localP) const
station-level method: does not depend on the strip view/layer, hence it cannot account for internal a...
double lengthCorrection(int measuresPhi, double stripPos) const
virtual int numberOfStrips(const Identifier &layerId) const override final
number of strips per layer
Amg::Vector3D localPos(const Amg::Vector3D &globalP) const
station-level method: does not depend on the strip view/layer, hence it cannot account for internal a...
int NphiStrips(int gasgaplayer) const
Amg::Vector3D localToGlobalCoords(const Amg::Vector3D &x, const Identifier &id) const
localToGlobalCoords and Transf connect the Gas Gap Frame (defined as a Sensitive Detector) to the Glo...
Amg::Transform3D nominalTransform(const Identifier &id) const
like tracking Transform but nominal - returns a transform not a reference to it
double getGasGapIntAlign_rott(int gasGap) const
Amg::Vector3D stripPosOnTrackingSurface(const Identifier &id) const
nominal strip pos in the tracking local frame of the measurement surface
Amg::Vector3D stripPos(const Identifier &id) const
takes into account internal alignment parameters, hence gives accurate answer
double xCoordinateInTrackingFrame(const Identifier &id) const
virtual double distanceToReadout(const Amg::Vector2D &pos, const Identifier &id) const override final
distance to readout.
Amg::Transform3D globalToLocalTransf(const Identifier &id) const
Amg::Vector3D nominalCenter(int gasGap) const
like tracking center but nominal - returns a Amg::Vector3D not a reference to it
CscReadoutElement(GeoVFullPhysVol *pv, const std::string &stName, MuonDetectorManager *mgr)
Amg::Vector3D nominalGlobalPos(const Amg::Vector3D &localP) const
ignores internal alignment parameters, hence gives generally incorrect answer
Amg::Transform3D localToGlobalTransf(const Identifier &id) const
virtual void fillCache() override
int NetaStrips(int gasgaplayer) const
Amg::Vector3D originForInternalALines(int gasGap) const
like tracking center but nominal - returns a Amg::Vector3D not a reference to it
Amg::Vector3D localWireLayerPos(const Identifier &id) const
virtual bool containsId(const Identifier &id) const override
Amg::Vector3D nominalStripPos(const Identifier &id) const
ignores internal alignment parameters, hence gives generally incorrect answer
Amg::Vector3D localStripLayerPos(const Identifier &id) const
int maxNumberOfStrips(int measuresPhi) const
void setCscInternalAlignmentPar(const ALinePar &)
double getGasGapIntAlign_s(int gasGap) const
Amg::Vector3D stripLayerPos(const Identifier &id) const
virtual const Trk::PlaneSurface & surface() const override
access to chamber surface (phi orientation), uses the first gas gap
virtual void clearCache() override final
clear the cache of the readout elememt
std::unique_ptr< SurfaceData > m_surfaceData
MuonClusterReadoutElement(GeoVFullPhysVol *pv, MuonDetectorManager *mgr, Trk::DetectorElemType detType)
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
Identifier identify() const override final
Returns the ATLAS Identifier of the MuonReadOutElement.
int stationEta(const Identifier &id) const
virtual int get_id(const IdentifierHash &hash_id, Identifier &id, const IdContext *context=0) const override
Create compact id from hash id (return == 0 for OK)
IdContext channel_context() const
id for channel
virtual const CscIdHelper & cscIdHelper() const =0
access to CscIdHelper
Abstract base class for surface bounds to be specified.
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
singleton-like access to IMessageSvc via open function and helper
Eigen::AngleAxisd AngleAxis3D
Eigen::Matrix< double, 3, 3 > RotationMatrix3D
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
Eigen::Translation< double, 3 > Translation3D
IMessageSvc * getMessageSvc(bool quiet=false)
Ensure that the Athena extensions are properly loaded.
Definition GeoMuonHits.h:27
int nStrips(const MuonGM::TgcReadoutElement &readoutEle, int layer)
Ensure that the ATLAS eigen extensions are properly loaded.