ATLAS Offline Software
MMT_Diamond.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 
8 namespace {
9  // The stereo angle is fixed and can be hardcoded
10  const double tan_stereo_angle = std::tan(0.02618);
11 
12  constexpr int bc_wind = 4; // fixed time window (in bunch crossings) during which the algorithm collects ART hits
13  constexpr int n_addc = 4;
14  constexpr int n_vmm = 128;
15 }
16 
17 
18 MMT_Diamond::MMT_Diamond(const int diamXthreshold, const bool uv, const int diamUVthreshold, const int roadSize,
19  const int olapEtaUp, const int olapEtaDown, const int olapStereoUp, const int olapStereoDown): AthMessaging(Athena::getMessageSvc(), "MMT_Diamond") {
20  m_xthr = diamXthreshold;
21  m_uvthr = diamUVthreshold;
22  m_uvflag = uv;
23  m_roadSize = roadSize;
24  m_roadSizeUpX = olapEtaUp;
25  m_roadSizeDownX = olapEtaDown;
26  m_roadSizeUpUV = olapStereoUp;
27  m_roadSizeDownUV = olapStereoDown;
28 }
29 
30 void MMT_Diamond::createRoads(std::vector<std::shared_ptr<MMT_Road> >& roads, const bool isLarge) const {
31  const char sec = (isLarge) ? 'L' : 'S';
32  /*
33  * This computation is done as follows: 1024 X roads
34  * MML: for i in [0,8] -> i*6 UV roads. Then: (1024-9)*6*9 UV roads
35  * MMS: for i in [0,6] -> i*6 UV roads. Then: (1024-7)*6*7 UV roads
36  */
37  const unsigned int vecRoads = (isLarge) ? 56050 : 43864;
38  roads.reserve(vecRoads);
39  int nroad = 8192/this->getRoadSize();
40  for (int i = 0; i < nroad; ++i) {
41  roads.emplace_back(std::make_shared<MMT_Road>(sec, m_roadSize, m_roadSizeUpX, m_roadSizeDownX, m_roadSizeUpUV, m_roadSizeDownUV, m_xthr, m_uvthr, i));
42 
43  /*
44  * The computation of "nuv" is:
45  * B = (1./std::tan(1.5/180.*M_PI));
46  * nuv = std::round( par->getlWidth() / (B * 0.4 * 2.)/this->getRoadSize() );
47  * As getlWidth() has to deal with the full wedge, only two (fixed by construction) integer values are allowed, according to small (7) or large (9) wedge
48  */
49  if(m_uvflag) {
50  const int nuv = (isLarge) ? 9 : 7;
51  for (int uv = 1; uv <= nuv; uv++) {
52  if (i-uv < 0) continue;
53 
54  roads.emplace_back(std::make_shared<MMT_Road>(sec, m_roadSize, m_roadSizeUpX, m_roadSizeDownX, m_roadSizeUpUV, m_roadSizeDownUV, m_xthr, m_uvthr, i, i+uv, i-uv));
55  roads.emplace_back(std::make_shared<MMT_Road>(sec, m_roadSize, m_roadSizeUpX, m_roadSizeDownX, m_roadSizeUpUV, m_roadSizeDownUV, m_xthr, m_uvthr, i, i-uv, i+uv));
56  roads.emplace_back(std::make_shared<MMT_Road>(sec, m_roadSize, m_roadSizeUpX, m_roadSizeDownX, m_roadSizeUpUV, m_roadSizeDownUV, m_xthr, m_uvthr, i, i+uv-1, i-uv));
57  roads.emplace_back(std::make_shared<MMT_Road>(sec, m_roadSize, m_roadSizeUpX, m_roadSizeDownX, m_roadSizeUpUV, m_roadSizeDownUV, m_xthr, m_uvthr, i, i-uv, i+uv-1));
58  roads.emplace_back(std::make_shared<MMT_Road>(sec, m_roadSize, m_roadSizeUpX, m_roadSizeDownX, m_roadSizeUpUV, m_roadSizeDownUV, m_xthr, m_uvthr, i, i-uv+1, i+uv));
59  roads.emplace_back(std::make_shared<MMT_Road>(sec, m_roadSize, m_roadSizeUpX, m_roadSizeDownX, m_roadSizeUpUV, m_roadSizeDownUV, m_xthr, m_uvthr, i, i+uv, i-uv+1));
60  }
61  }
62  }
63 }
64 
65 void MMT_Diamond::findDiamonds(std::vector<std::shared_ptr<MMT_Hit> >& hits, const std::vector<std::shared_ptr<MMT_Road> >& roads, std::vector<slope_t>& diamondSlopes, const int sectorPhi) const {
66 
67  // Comparison with lambda function (easier to implement)
68  std::sort(hits.begin(), hits.end(), [](const auto &h1, const auto &h2){ return h1->getBC() < h2->getBC(); });
69  const int bc_start = hits.front()->getBC();
70  const int bc_end = hits.front()->getBC() + 16;
71  ATH_MSG_DEBUG("Window Start: " << bc_start << " - Window End: " << bc_end);
72 
73  std::vector<std::shared_ptr<MMT_Hit> > hits_now;
74  std::vector< std::pair<int, float> > vmm_same;
75  std::vector< std::pair<int, int> > addc_same;
76  std::vector<int> to_erase;
77 
78  // each road makes independent triggers, evaluated on each BC
79  unsigned int ibc = 0;
80  for (int bc = hits.front()->getBC(); bc < bc_end; bc++) {
81  // Cleaning stuff
82  hits_now.clear();
83 
84  for (unsigned int j = ibc; j < hits.size(); j++) {
85  if (hits[j]->getBC() == bc) hits_now.push_back(hits[j]);
86  else if (hits[j]->getBC() > bc) {
87  ibc = j;
88  break;
89  }
90  }
91 
92  // Simulate harware filters: ART hits + ADDC filter
93  for (unsigned int ib = 0; ib < 8; ib++) { //loop on plane from 0 to 7
94  // VMM-ART-hit filter
95  for (int j = 0; j < n_vmm; j++) {
96  vmm_same.clear();
97  unsigned int k = 0;
98  for (const auto &hit_pointer: hits_now) {
99  if (static_cast<unsigned int>(hit_pointer->getPlane()) != ib) continue;
100  if (hit_pointer->getVMM() == j){
101  vmm_same.push_back( std::make_pair(k, hit_pointer->getTime()) );
102  }
103  k++;
104  }
105  if (vmm_same.size() > 1) {
106  to_erase.clear();
107  std::sort(vmm_same.begin(), vmm_same.end(), [](const std::pair<int, float>& p1, const std::pair<int, float>& p2) { return p1.second < p2.second; });
108  for (auto pair: vmm_same) to_erase.push_back(pair.first);
109  // reverse and erase
110  std::sort(to_erase.rbegin(), to_erase.rend());
111  to_erase.pop_back(); //removes the hit with the earliest time
112  for (auto l : to_erase) {
113  hits_now.erase(hits_now.begin() + l);
114  }
115  }
116  }
117  // ADDC-like filter
118  for (int ia = 0; ia < n_addc; ia++) { // From 0 to 3 (local index of the ART ASIC in the layer)
119  addc_same.clear();
120  for (unsigned int k = 0; k < hits_now.size(); k++) {
121  if ((unsigned int)(hits_now[k]->getPlane()) != ib) continue;
122  int istrip = (std::abs(hits_now[k]->getStationEta())-1) * (64*8*10) + hits_now[k]->getChannel(); //needed the global strip index on the sector layer (getChannel returns chamber's local strip index)
123  if (hits_now[k]->getART() == ia) addc_same.emplace_back(k, istrip);
124  }
125 
126  if (addc_same.size() > 8) {
127  // priority encode the hits by channel number; remember hits 8+
128  to_erase.clear();
129 
130  std::sort(addc_same.begin(), addc_same.end(), [](const std::pair<int, int>& p1, const std::pair<int, int>& p2) { return p1.second < p2.second; });
131  for (unsigned int it = 8; it < addc_same.size(); it++) to_erase.push_back(addc_same[it].first);
132 
133  // reverse and erase
134  std::sort(to_erase.rbegin(), to_erase.rend());
135  for (auto l : to_erase) {
136  hits_now.erase(hits_now.begin() + l);
137  }
138  }
139  }
140  } // loop on plane for VMM and ART ASIC filter
141 
142  for (auto &road : roads) {
143  road->incrementAge(bc_wind);
144  if (!hits_now.empty()) road->addHits(hits_now);
145 
146  if (road->checkCoincidences(bc_wind) && bc >= (bc_start - 1)) {
147 
148  ATH_MSG_DEBUG("------------------------------------------------------------------");
149  ATH_MSG_DEBUG("Coincidence FOUND @BC: " << bc);
150  ATH_MSG_DEBUG("Road (x, u, v, count): (" << road->iRoadx() << ", " << road->iRoadu() << ", " << road->iRoadv() << ", " << road->countHits() << ")");
151  ATH_MSG_DEBUG("------------------------------------------------------------------");
152 
153  std::vector<int> bcidVec;
154  for (const auto &hit: road->getHitVector()) {
155  bcidVec.push_back(hit->getBC());
156  }
157  std::sort(bcidVec.begin(), bcidVec.end());
158 
159  // evaluating mode of the BCID of the hits in the diamond
160  // default setting in the firmware is the mode of the hits's bcid in the diamond
161  int bcidVal=bcidVec[0], bcidCount=1, modeCount=1, bcidMode=bcidVec[0];
162  for (unsigned int i=1; i<bcidVec.size(); i++){
163  if (bcidVec[i] == bcidVal){
164  bcidCount++;
165  } else {
166  bcidCount = 1;
167  bcidVal = bcidVec[i];
168  }
169  if (bcidCount > modeCount) {
170  modeCount = bcidCount;
171  bcidMode = bcidVal;
172  }
173  }
174 
175  slope_t slope;
176  slope.BC = bcidMode;
177  slope.totalCount = road->countHits();
178  slope.realCount = road->countRealHits();
179  slope.iRoad = road->iRoadx();
180  slope.iRoadu = road->iRoadu();
181  slope.iRoadv = road->iRoadv();
182  slope.uvbkg = road->countUVHits(true); // the bool in the following 4 functions refers to background/noise hits
183  slope.xbkg = road->countXHits(true);
184  slope.uvmuon = road->countUVHits(false);
185  slope.xmuon = road->countXHits(false);
186  slope.age = slope.BC - bc_start;
187  slope.mxl = road->mxl();
188  slope.my = road->avgSofX(); // defined as my in ATL-COM-UPGRADE-2015-033
189  slope.uavg = road->avgSofUV(2,4);
190  slope.vavg = road->avgSofUV(3,5);
191  slope.mx = (slope.uavg-slope.vavg)/(2.*tan_stereo_angle);
192  const double theta = std::atan(std::sqrt(std::pow(slope.mx,2) + std::pow(slope.my,2)));
193  slope.theta = (slope.my > 0.) ? theta : M_PI - theta;
194  slope.eta = -1.*std::log(std::tan(slope.theta/2.));
195  slope.dtheta = (slope.mxl - slope.my)/(1. + slope.mxl*slope.my);
196  slope.side = (slope.my > 0.) ? 'A' : 'C';
197  slope.phi = std::atan(slope.mx/slope.my);
198  slope.phiShf = phiShift(sectorPhi, slope.phi, slope.side);
199  slope.lowRes = road->evaluateLowRes();
200 
201  diamondSlopes.push_back(slope);
202  }
203  }
204  }
205 }
206 
207 double MMT_Diamond::phiShift(const int n, const double phi, const char side) const {
208  double Phi = (side == 'A') ? -phi : phi;
209  double shift = (n > 8) ? (16-n)*M_PI/8. : n*M_PI/8.;
210  if (n < 8) return (Phi + shift);
211  else if (n == 8) return (Phi + ((Phi > 0.) ? -1. : 1.)*shift);
212  else return (Phi - shift);
213 }
slope_t::eta
double eta
Definition: MMT_Diamond.h:32
MMT_Diamond::findDiamonds
void findDiamonds(std::vector< std::shared_ptr< MMT_Hit > > &hits, const std::vector< std::shared_ptr< MMT_Road > > &roads, std::vector< slope_t > &diamondSlopes, const int sectorPhi) const
Definition: MMT_Diamond.cxx:65
TRTCalib_Extractor.hits
hits
Definition: TRTCalib_Extractor.py:35
slope_t::BC
int BC
Definition: MMT_Diamond.h:15
MMT_Diamond::getRoadSize
int getRoadSize() const
Definition: MMT_Diamond.h:50
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:67
slope_t::uavg
double uavg
Definition: MMT_Diamond.h:28
slope_t::my
double my
Definition: MMT_Diamond.h:27
slope_t::xmuon
unsigned int xmuon
Definition: MMT_Diamond.h:24
theta
Scalar theta() const
theta method
Definition: AmgMatrixBasePlugin.h:75
TRTCalib_cfilter.p1
p1
Definition: TRTCalib_cfilter.py:130
skel.it
it
Definition: skel.GENtoEVGEN.py:407
M_PI
#define M_PI
Definition: ActiveFraction.h:11
PlotCalibFromCool.ib
ib
Definition: PlotCalibFromCool.py:419
UploadAMITag.l
list l
Definition: UploadAMITag.larcaf.py:157
slope_t::iRoadu
int iRoadu
Definition: MMT_Diamond.h:19
Phi
@ Phi
Definition: RPCdef.h:8
MMT_Diamond::m_uvthr
int m_uvthr
Definition: MMT_Diamond.h:57
slope_t::totalCount
unsigned int totalCount
Definition: MMT_Diamond.h:16
read_hist_ntuple.h1
h1
Definition: read_hist_ntuple.py:21
slope_t::vavg
double vavg
Definition: MMT_Diamond.h:29
Athena::getMessageSvc
IMessageSvc * getMessageSvc(bool quiet=false)
Definition: getMessageSvc.cxx:20
drawFromPickle.atan
atan
Definition: drawFromPickle.py:36
MMT_Diamond::phiShift
double phiShift(const int n, const double phi, const char side) const
Definition: MMT_Diamond.cxx:207
TRT::Hit::side
@ side
Definition: HitInfo.h:83
slope_t::side
char side
Definition: MMT_Diamond.h:36
TRTCalib_cfilter.p2
p2
Definition: TRTCalib_cfilter.py:131
MMT_Diamond::m_roadSizeDownX
int m_roadSizeDownX
Definition: MMT_Diamond.h:56
slope_t::dtheta
double dtheta
Definition: MMT_Diamond.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:85
MMT_Diamond::m_roadSizeUpUV
int m_roadSizeUpUV
Definition: MMT_Diamond.h:56
Athena
Some weak symbol referencing magic...
Definition: AthLegacySequence.h:21
beamspotman.n
n
Definition: beamspotman.py:729
slope_t::phiShf
double phiShf
Definition: MMT_Diamond.h:35
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
slope_t::theta
double theta
Definition: MMT_Diamond.h:31
MMT_Diamond::MMT_Diamond
MMT_Diamond(const int diamXthreshold, const bool uv, const int diamUVthreshold, const int roadSize, const int olapEtaUp, const int olapEtaDown, const int olapStereoUp, const int olapStereoDown)
Definition: MMT_Diamond.cxx:18
slope_t::mx
double mx
Definition: MMT_Diamond.h:30
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
MMT_Diamond::m_roadSize
int m_roadSize
Definition: MMT_Diamond.h:56
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
slope_t::iRoad
int iRoad
Definition: MMT_Diamond.h:18
slope_t::iRoadv
int iRoadv
Definition: MMT_Diamond.h:20
MMT_Diamond::m_roadSizeUpX
int m_roadSizeUpX
Definition: MMT_Diamond.h:56
MMT_Diamond::m_uvflag
bool m_uvflag
Definition: MMT_Diamond.h:55
MMT_Diamond::m_xthr
int m_xthr
Definition: MMT_Diamond.h:57
slope_t::age
int age
Definition: MMT_Diamond.h:25
slope_t::realCount
unsigned int realCount
Definition: MMT_Diamond.h:17
MMT_Diamond::m_roadSizeDownUV
int m_roadSizeDownUV
Definition: MMT_Diamond.h:56
slope_t::lowRes
bool lowRes
Definition: MMT_Diamond.h:37
slope_t::phi
double phi
Definition: MMT_Diamond.h:34
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
slope_t::mxl
double mxl
Definition: MMT_Diamond.h:26
MMT_Diamond::createRoads
void createRoads(std::vector< std::shared_ptr< MMT_Road > > &roads, const bool isLarge) const
Definition: MMT_Diamond.cxx:30
slope_t::xbkg
unsigned int xbkg
Definition: MMT_Diamond.h:22
slope_t
Definition: MMT_Diamond.h:13
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
MMT_Diamond.h
slope_t::uvbkg
unsigned int uvbkg
Definition: MMT_Diamond.h:21
fitman.k
k
Definition: fitman.py:528
slope_t::uvmuon
unsigned int uvmuon
Definition: MMT_Diamond.h:23