ATLAS Offline Software
Loading...
Searching...
No Matches
NswStationFitter.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4#include "NswStationFitter.h"
6
7#include "RecMuonRoIUtils.h"
8
10
11#include <cmath>
12#include <vector>
13#include <array>
14#include <stdexcept>
15
16namespace{
17 constexpr double ZERO_LIMIT = 1.e-9;
18}
19
20static const double TanM1p5 = std::tan(-1.5/360.*2.*M_PI);
21static const double TanP1p5 = std::tan(1.5/360.*2.*M_PI);
22static const double CosM1p5 = std::cos(-1.5/360.*2.*M_PI);
23static const double CosP1p5 = std::cos(1.5/360.*2.*M_PI);
24static const double SinM1p5 = std::sin(-1.5/360.*2.*M_PI);
25static const double SinP1p5 = std::sin(1.5/360.*2.*M_PI);
26
28 const std::string& name,
29 const IInterface* parent):
30 AthAlgTool(type,name,parent)
31{
32}
33
35 TrigL2MuonSA::TrackPattern& trackPattern,
36 TrigL2MuonSA::StgcHits& stgcHits,
37 TrigL2MuonSA::MmHits& mmHits) const
38{
39
40 ATH_MSG_DEBUG("NswStationFitter::findSuperPoints() was called.");
41
42 // selection for sTGC hits, RoI matching based
43 ATH_CHECK( selectStgcHits(p_roids,trackPattern.stgcSegment) );
44 ATH_CHECK( selectMmHits(p_roids,trackPattern.mmSegment) );
45
48
49 bool isLargeStgc = false;
50 bool isSmallStgc = false;
51 if(stgcHits.size() != 0){
52 for(unsigned int iHit = 0; iHit < stgcHits.size(); iHit++){
53 if(stgcHits.at(iHit).isOutlier == 0){
54 if(stgcHits.at(iHit).stationName == 58) isLargeStgc = true;
55 else if(stgcHits.at(iHit).stationName == 57) isSmallStgc = true;
56 if(isLargeStgc && isSmallStgc) continue;
57 }
58 }
59 }
60 if(mmHits.size() != 0){
61 for(unsigned int iHit = 0; iHit < mmHits.size(); iHit++){
62 if(mmHits.at(iHit).isOutlier == 0){
63 if(isLargeStgc){
64 if(mmHits.at(iHit).stationName == 55) mmHits.at(iHit).isOutlier = 1;
65 } else if(isSmallStgc) {
66 if(mmHits.at(iHit).stationName == 56) mmHits.at(iHit).isOutlier = 1;
67 }
68 }
69 }
70 }
71 ATH_CHECK( MakeSegment(trackPattern,stgcHits) );
72 ATH_CHECK( MakeSegment(trackPattern,mmHits) );
73
74 ATH_MSG_DEBUG("Number of sTGC and MM hits for SPs " << trackPattern.stgcSegment.size() << " " << trackPattern.mmSegment.size());
75 if (trackPattern.stgcSegment.size() < 9 && trackPattern.mmSegment.size() < 6) {
76 ATH_MSG_DEBUG("Number of sTGC and MM hits for SPs is small " << trackPattern.stgcSegment.size() + trackPattern.mmSegment.size());
77 }
78 else {
79 ATH_CHECK( calcMergedHit(trackPattern) );
80 }
81
82
83 return StatusCode::SUCCESS;
84
85}
86
88 TrigL2MuonSA::StgcHits& stgcHits) const
89{
90
91 TrigL2MuonSA::StgcHits selectedStgcHits;
92 selectedStgcHits.clear();
93
94 // define region where RoI is near
95 double etaMin = p_roids->eta() - 1.;
96 double etaMax = p_roids->eta() + 1.;
97 double phiMin = p_roids->phi() - 1.;
98 double phiMax = p_roids->phi() + 1.;
99 if( phiMin > M_PI ) phiMin -= 2*M_PI;
100 if( phiMax > M_PI ) phiMax -= 2*M_PI;
101 if( phiMin < -1.*M_PI ) phiMin += 2*M_PI;
102 if( phiMax < -1.*M_PI ) phiMax += 2*M_PI;
103 // boolian to check if sTGC hits are near RoI
104 bool inRoiEta, inRoiPhi, inRoi;
105
106 // loop over sTGC digits.
107 unsigned int iHit;
108 if (stgcHits.size()>0) {
109 for (iHit = 0; iHit < stgcHits.size(); iHit++){
110 // Get the digit point.
111 TrigL2MuonSA::StgcHitData& hit = stgcHits[iHit];
112
113 // check if sTGC hits are near RoI
114 inRoiEta = false; inRoiPhi = false; inRoi = false;
115 if ( etaMin<=hit.eta && hit.eta<=etaMax ) inRoiEta = true;
116 if ( phiMin<=phiMax && phiMin<=hit.phi && hit.phi<=phiMax ) inRoiPhi= true;
117 if ( phiMin>phiMax && (phiMin<=hit.phi || hit.phi<=phiMax)) inRoiPhi= true;
118 if ( inRoiEta && inRoiPhi ) inRoi = true;
119 ATH_MSG_DEBUG("sTGC hits eta = "<<hit.eta<<", phi = "<<hit.phi<<", r = "<<hit.r<<", z = "<<hit.z<<", stationEta = "<<hit.stationEta<<", stationPhi = "<<hit.stationPhi<<", channelType = "<<hit.channelType<<", stationName = "<<hit.stationName<<",layerNumber ="<<hit.layerNumber<<", matched RoI? = "<<inRoi);
120 // pushback if the hit is near RoI
121 if (!inRoi){
122 continue;
123 }
124 selectedStgcHits.push_back(hit);
125 }
126 }
127
128 stgcHits.clear();
129 stgcHits = std::move(selectedStgcHits);
130
131 return StatusCode::SUCCESS;
132
133}
134
136 TrigL2MuonSA::MmHits& mmHits) const
137{
138
139 TrigL2MuonSA::MmHits selectedMmHits;
140 selectedMmHits.clear();
141
142 // define region where RoI is near
143 double etaMin = p_roids->eta() - 1.;
144 double etaMax = p_roids->eta() + 1.;
145 double phiMin = p_roids->phi() - 1.;
146 double phiMax = p_roids->phi() + 1.;
147 if( phiMin > M_PI ) phiMin -= 2*M_PI;
148 if( phiMax > M_PI ) phiMax -= 2*M_PI;
149 if( phiMin < -1.*M_PI ) phiMin += 2*M_PI;
150 if( phiMax < -1.*M_PI ) phiMax += 2*M_PI;
151 // boolian to check if sTGC hits are near RoI
152 bool inRoiEta, inRoiPhi, inRoi;
153
154 // loop over MM digits.
155 unsigned int iHit;
156 if (mmHits.size()>0) {
157 for (iHit = 0; iHit < mmHits.size(); iHit++){
158
159 // Get the digit point.
160 TrigL2MuonSA::MmHitData& hit = mmHits[iHit];
161
162 // check if MM hits are near RoI
163 inRoiEta = false; inRoiPhi = false; inRoi = false;
164 if ( etaMin<=hit.eta && hit.eta<=etaMax ) inRoiEta = true;
165 if ( phiMin<=phiMax && phiMin<=hit.phi && hit.phi<=phiMax ) inRoiPhi= true;
166 if ( phiMin>phiMax && (phiMin<=hit.phi || hit.phi<=phiMax)) inRoiPhi= true;
167 if ( inRoiEta && inRoiPhi ) inRoi = true;
168 ATH_MSG_DEBUG("MM hits eta = "<<hit.eta<<", phi = "<<hit.phi<<", r = "<<hit.r<<", z = "<<hit.z<<", stationEta = "<<hit.stationEta<<", stationPhi = "<<hit.stationPhi<<", stationName = "<<hit.stationName<<", matched RoI? = "<<inRoi);
169
170 // pushback if the hit is near RoI
171 if (!inRoi){
172 continue;
173 }
174 selectedMmHits.push_back(hit);
175 }
176 }
177
178 mmHits.clear();
179 mmHits = std::move(selectedMmHits);
180
181 return StatusCode::SUCCESS;
182
183}
184
186{
187
188 TrigL2MuonSA::StgcHits stgcHits = trackPattern.stgcSegment;
189 TrigL2MuonSA::MmHits mmHits = trackPattern.mmSegment;
190
191 if(stgcHits.size()==0 && mmHits.size()==0)
192 return StatusCode::SUCCESS;
193
194 //superpoint information
195 float rWeightedCenter=0.,zWeightedCenter=0.,phiWeightedCenter=0.;
196 int totNumRWeightedCenter=0.,totNumZWeightedCenter=0.,totNumPhiWeightedCenter=0.;
197 float localPhiCenter=0., localPhi;
198
199 // loop over sTGC digits.
200 unsigned int iHit;
201 if (stgcHits.size()>0) {
202 for (iHit = 0; iHit < stgcHits.size(); iHit++){
203
204 // Get the digit point.
205 TrigL2MuonSA::StgcHitData& hit = stgcHits[iHit];
206
207 if (iHit==0 && hit.stationPhi<=5) localPhiCenter = 0.25 * M_PI * ((float)hit.stationPhi-1.);
208 if (iHit==0 && hit.stationPhi> 5) localPhiCenter = 0.25 * M_PI * ((float)hit.stationPhi-9.);
209 if (hit.stationName == 57){
210 localPhiCenter += M_PI/8.; // small sTGC sectors
211 if (hit.stationPhi == 5) localPhiCenter -= 2 * M_PI;
212 }
213
214 localPhi = hit.phi - localPhiCenter;
215 if (localPhi > M_PI) localPhi -= 2.0*M_PI;
216 if (localPhi < -1.*M_PI) localPhi += 2.0*M_PI;
217 // calculate Weighted Center
218 if (hit.channelType == 1) { // strip
219 rWeightedCenter += hit.r;
220 totNumRWeightedCenter += 1;
221 }
222 if (hit.channelType == 2) { // wire
223 phiWeightedCenter += localPhi;
224 totNumPhiWeightedCenter += 1;
225 }
226 zWeightedCenter += hit.z;
227 totNumZWeightedCenter += 1;
228 }
229 }
230
231 // loop over MM digits.
232 if (mmHits.size()>0) {
233 for (iHit = 0; iHit < mmHits.size(); iHit++){
234
235 // Get the digit point.
236 TrigL2MuonSA::MmHitData& hit = mmHits[iHit];
237
238 if (hit.stationName == 55){
239 localPhiCenter += M_PI/8.; // small MM sectors
240 if (hit.stationPhi == 5) localPhiCenter -= 2 * M_PI;
241 }
242
243 localPhi = hit.phi - localPhiCenter;
244 if (localPhi > M_PI) localPhi -= 2.0*M_PI;
245 if (localPhi < -1.*M_PI) localPhi += 2.0*M_PI;
246 }
247 }
248
249 // calculate Weighted Center
250 if (totNumRWeightedCenter!=0) rWeightedCenter /= totNumRWeightedCenter;
251 if (totNumPhiWeightedCenter!=0) phiWeightedCenter /= totNumPhiWeightedCenter;
252 if (totNumZWeightedCenter!=0) zWeightedCenter /= totNumZWeightedCenter;
253
254 // store superpoint info in TrackData
256 TrigL2MuonSA::SuperPoint* superPoint = &(trackPattern.superPoints[inner]);
257 superPoint->R = rWeightedCenter;
258 superPoint->Phim = phiWeightedCenter+localPhiCenter;
259 superPoint->Z = zWeightedCenter;
260 superPoint->Npoint = totNumZWeightedCenter;
261 if (zWeightedCenter!=0) superPoint->Alin = rWeightedCenter/zWeightedCenter;
262 superPoint->Blin = 0.;
263
264 ATH_MSG_DEBUG("Nsw Super Point r/phi/z/slope = "<<superPoint->R<<"/"<<superPoint->Phim<<"/"<<superPoint->Z<<"/"<<superPoint->Alin);
265
266 return StatusCode::SUCCESS;
267
268}
269
271{
272 if(stgcHits.size() == 0) return StatusCode::SUCCESS;
273 int hitsInRoad = 0;
274 for(unsigned int iHit = 0; iHit < stgcHits.size(); iHit++){
275 if(stgcHits.at(iHit).isOutlier == 0){
276 hitsInRoad++;
277 stgcHits.at(iHit).isOutlier = 1;
278 }
279 }
280 if(hitsInRoad == 0) return StatusCode::SUCCESS;
281
282 if(hitsInRoad < 9) {
283 ATH_MSG_DEBUG("Number of STGC hits is too small, at least 9 hits required : "<<hitsInRoad<<" hits");
284 return StatusCode::SUCCESS;
285 } else if(hitsInRoad > 100) {
286 ATH_MSG_WARNING("Number of STGC hits is too large, at most 100 hits allowed : "<<hitsInRoad<<" hits");
287 return StatusCode::SUCCESS;
288 }
289
290 // cassifyDataEachLayer
291 std::array<std::vector<int>, 8> strHitIdByLayer;
292 std::array<std::vector<int>, 8> wireHitIdByLayer;
293 for(unsigned int iHit = 0; iHit < stgcHits.size(); ++iHit){
294 if(stgcHits.at(iHit).isOutlier != 1) continue;
295 int layerNumber = stgcHits.at(iHit).layerNumber;
296 if (layerNumber > 7) {
297 ATH_MSG_WARNING("STGC hit layer number > 7");
298 continue;
299 }
300 if(stgcHits.at(iHit).channelType == 1){
301 strHitIdByLayer[layerNumber].push_back(iHit);
302 }else if(stgcHits.at(iHit).channelType == 2){
303 wireHitIdByLayer[layerNumber].push_back(iHit);
304 }
305 }
306 ATH_MSG_DEBUG("@@STGC@@ strip Nhits " << strHitIdByLayer[0].size()
307 << " " << strHitIdByLayer[1].size()
308 << " " << strHitIdByLayer[2].size()
309 << " " << strHitIdByLayer[3].size()
310 << " " << strHitIdByLayer[4].size()
311 << " " << strHitIdByLayer[5].size()
312 << " " << strHitIdByLayer[6].size()
313 << " " << strHitIdByLayer[7].size());
314 ATH_MSG_DEBUG("@@STGC@@ wire Nhits " << wireHitIdByLayer[0].size()
315 << " " << wireHitIdByLayer[1].size()
316 << " " << wireHitIdByLayer[2].size()
317 << " " << wireHitIdByLayer[3].size()
318 << " " << wireHitIdByLayer[4].size()
319 << " " << wireHitIdByLayer[5].size()
320 << " " << wireHitIdByLayer[6].size()
321 << " " << wireHitIdByLayer[7].size());
322
323 std::vector< std::array<int, 8> > strHitIds; // Candidates' sets of strip hit ids in 8 layers
324 findSetOfStgcHitIds(stgcHits, strHitIdByLayer, strHitIds);
325 std::vector< std::array<int, 8> > wireHitIds; // Candidates' sets of wire hit ids in 8 layers
326 findSetOfStgcHitIds(stgcHits, wireHitIdByLayer, wireHitIds);
327 ATH_MSG_DEBUG("@@STGC@@ strip wire " << strHitIds.size() << " " << wireHitIds.size());
328
329 bool isLargeStrip = false;
330 bool isSmallStrip = false;
331 for (unsigned int iHit = 0; iHit < strHitIds.size(); ++iHit) {
332 std::array<int, 8> hitIds = strHitIds.at(iHit);
333 for (unsigned int iLayer = 0; iLayer < 8; ++iLayer) {
334 if (hitIds[iLayer] != -1) {
335 if(stgcHits.at(hitIds[iLayer]).stationName == 58) isLargeStrip = true;
336 else if(stgcHits.at(hitIds[iLayer]).stationName == 57) isSmallStrip = true;
337 stgcHits.at(hitIds[iLayer]).isOutlier = 0;
338 }
339 }
340 }
341 for (unsigned int iHit = 0; iHit < wireHitIds.size(); ++iHit) {
342 std::array<int, 8> hitIds = wireHitIds.at(iHit);
343 for (unsigned int iLayer = 0; iLayer < 8; ++iLayer) {
344 if (hitIds[iLayer] != -1) {
345 if(isLargeStrip){
346 if(stgcHits.at(hitIds[iLayer]).stationName == 58){
347 stgcHits.at(hitIds[iLayer]).isOutlier = 0;
348 }
349 }
350 else if(isSmallStrip){
351 if(stgcHits.at(hitIds[iLayer]).stationName == 57){
352 stgcHits.at(hitIds[iLayer]).isOutlier = 0;
353 }
354 }
355 }
356 }
357 }
358 return StatusCode::SUCCESS;
359
360}
361
363 const std::array<std::vector<int>,8> & hitIdByLayer,
364 std::vector<std::array<int, 8>>& hitIdsCandidate) const
365{
366 double NSWCenterZ = 7526.329;
367 int side = 0;
368
369 bool isStrip = 0;
370 for (unsigned int iLayer = 0; iLayer < 8; ++iLayer) {
371 if ( hitIdByLayer[iLayer].size() > 0) {
372 side = std::abs(stgcHits.at(hitIdByLayer[iLayer].at(0)).z)/stgcHits.at(hitIdByLayer[iLayer].at(0)).z;
373 if ( stgcHits.at(hitIdByLayer[iLayer].at(0)).channelType == 1 ){
374 isStrip = 1;
375 break;
376 }
377 }
378 }
379 NSWCenterZ = NSWCenterZ * side;
380
381 std::array<std::vector<unsigned long int>,4> hitIdsInTwo;
382 std::array<std::vector<double>,4> slopeInTwo;
383 std::array<std::vector<double>,4> interceptInTwo;
384
385 // Loop over pairs of the i-th and the (i+4)-th layers
386 for(unsigned int iPair = 0; iPair < 4; ++iPair){
387 unsigned int nHitsInInner = hitIdByLayer[iPair].size();
388 unsigned int nHitsInOuter = hitIdByLayer[iPair+4].size();
389 if ( nHitsInInner > 0xffff-1 || nHitsInOuter > 0xffff-1) {
390 ATH_MSG_WARNING("Number of Stgc hits in layers exceeds the limit of (2^16 - 1) : Number of Stgc hits in "<<iPair<<"th layer = "<< nHitsInInner
391 <<", Number of Stgc hits in "<<iPair+4<<"th layer = "<<nHitsInOuter);
392 ATH_MSG_WARNING("Number of Stgc hits is limitted to (2^16 - 1) and hits with id more than (2^16 -1) will be trancated.");
393 if (nHitsInInner > 0xffff-1) {nHitsInInner = 0xffff-1;}
394 if (nHitsInOuter > 0xffff-1) {nHitsInOuter = 0xffff-1;}
395 }
396
397 std::array<bool, 256> foundCounterparts{};
398 // Loop over hits in the i-th layer
399 for(unsigned int iHit = 0; iHit < nHitsInInner; ++iHit){
400 bool foundCounterpart = 0;
401
402 double z[2] = {};
403 double r[2] = {};
404
405 int iHitId = hitIdByLayer[iPair].at(iHit);
406 if(isStrip){
407 r[0] = stgcHits.at(iHitId).r;
408 z[0] = stgcHits.at(iHitId).z;
409 } else {
410 double localPhiCenter;
411 if (stgcHits.at(iHitId).stationPhi<=5) {
412 localPhiCenter = 0.25 * M_PI * ((double)stgcHits.at(iHitId).stationPhi-1.);
413 } else {
414 localPhiCenter = 0.25 * M_PI * ((double)stgcHits.at(iHitId).stationPhi-9.);
415 }
416
417 if (stgcHits.at(iHitId).stationName == 57){
418 localPhiCenter += M_PI/8.; // small sTGC sectors
419 if (stgcHits.at(iHitId).stationPhi == 5) localPhiCenter -= 2. * M_PI;
420 }
421
422 double phiProj = stgcHits.at(iHitId).phi - localPhiCenter;
423 if (phiProj > M_PI) phiProj -= 2.0*M_PI;
424 if (phiProj < -1.*M_PI) phiProj += 2.0*M_PI;
425 r[0] = stgcHits.at(iHitId).r;
426 z[0] = phiProj;
427 }
428
429 // Loop over hits in the (i+4)-th layer
430 for(unsigned int jHit = 0; jHit < nHitsInOuter; ++jHit){
431 int jHitId = hitIdByLayer[iPair+4].at(jHit);
432 double slope, intercept;
433 if(isStrip) {
434 r[1] = stgcHits.at(jHitId).r;
435 z[1] = stgcHits.at(jHitId).z;
436 slope = (r[1] - r[0]) / (z[1] - z[0]);
437 intercept = slope*(0. - z[0]) + r[0];
438 // select pairs whose slops in limited regions
439 if(std::abs(slope) < 0.14 || std::abs(slope) > 0.6 || std::abs(intercept) > 300.) continue;
440 } else {
441 double localPhiCenter;
442 if (stgcHits.at(jHitId).stationPhi<=5) {
443 localPhiCenter = 0.25 * M_PI * ((double)stgcHits.at(jHitId).stationPhi-1.);
444 } else {
445 localPhiCenter = 0.25 * M_PI * ((double)stgcHits.at(jHitId).stationPhi-9.);
446 }
447
448 if (stgcHits.at(jHitId).stationName == 57){
449 localPhiCenter += M_PI/8.; // small sTGC sectors
450 if (stgcHits.at(jHitId).stationPhi == 5) localPhiCenter -= 2 * M_PI;
451 }
452
453 double phiProj = stgcHits.at(jHitId).phi - localPhiCenter;
454 if (phiProj > M_PI) phiProj -= 2.0*M_PI;
455 if (phiProj < -1.*M_PI) phiProj += 2.0*M_PI;
456 r[1] = stgcHits.at(jHitId).r;
457 z[1] = phiProj;
458 slope = (z[0]+z[1])/2.;
459 intercept = (r[0]+r[1])/2.;
460 if(std::abs(r[0]*std::sin(z[0]) - r[1]*std::sin(z[1])) > 300.) continue;
461 }
462
463 unsigned int encodedIds = (iHitId<<16) + jHitId;
464 hitIdsInTwo[iPair].push_back(encodedIds);
465 slopeInTwo[iPair].push_back(slope);
466 interceptInTwo[iPair].push_back(intercept);
467
468 foundCounterpart = 1;
469 foundCounterparts.at(jHit) = 1;
470 }//end of jHit in the (i+4)-th layer
471 if(!foundCounterpart){ // in case of no counterpart in the (i+4)-th layer
472 unsigned int encodedIds = (iHitId<<16) + 0xffff; // fill all bits with 1 for hit id for the layer with no hit
473 hitIdsInTwo[iPair].push_back(encodedIds);
474 if(isStrip) {
475 slopeInTwo[iPair].push_back(r[0]/z[0]);
476 interceptInTwo[iPair].push_back(0.);
477 } else {
478 slopeInTwo[iPair].push_back(z[0]);
479 interceptInTwo[iPair].push_back(r[0]);
480 }
481 }
482 }//end of iHit in the i-th layer
483 // Loop over hits in the (i+4)-th layer
484 for(unsigned int jHit = 0; jHit < nHitsInOuter; ++jHit){
485 if (!foundCounterparts.at(jHit)) {
486 int jHitId = hitIdByLayer[iPair+4].at(jHit);
487 unsigned int encodedIds = 0xffff0000 + jHitId; // fill all bits with 1 for hit id for the layer with no hit
488 hitIdsInTwo[iPair].push_back(encodedIds);
489 if(isStrip) {
490 slopeInTwo[iPair].push_back(stgcHits.at(jHitId).r/stgcHits.at(jHitId).z);
491 interceptInTwo[iPair].push_back(0.);
492 } else {
493 double localPhiCenter;
494 if (stgcHits.at(jHitId).stationPhi<=5) {
495 localPhiCenter = 0.25 * M_PI * ((double)stgcHits.at(jHitId).stationPhi-1.);
496 } else {
497 localPhiCenter = 0.25 * M_PI * ((double)stgcHits.at(jHitId).stationPhi-9.);
498 }
499 if (stgcHits.at(jHitId).stationName == 57){
500 localPhiCenter += M_PI/8.; // small sTGC sectors
501 if (stgcHits.at(jHitId).stationPhi == 5) localPhiCenter -= 2 * M_PI;
502 }
503
504 double phiProj = stgcHits.at(jHitId).phi - localPhiCenter;
505 if (phiProj > M_PI) phiProj -= 2.0*M_PI;
506 if (phiProj < -1.*M_PI) phiProj += 2.0*M_PI;
507 slopeInTwo[iPair].push_back(phiProj);
508 interceptInTwo[iPair].push_back(stgcHits.at(jHitId).r);
509 }
510 }
511 }
512 }//end of pair loop
513
514 ATH_MSG_DEBUG("@@STGC@@ isStrip= " << isStrip << " Npairs " << hitIdsInTwo[0].size() << " " << hitIdsInTwo[1].size() << " " << hitIdsInTwo[2].size() << " " << hitIdsInTwo[3].size());
515 for (unsigned int iLayer = 0; iLayer < 4; ++ iLayer) {
516 for (unsigned int iPair = 0; iPair < slopeInTwo[iLayer].size(); ++iPair) {
517 ATH_MSG_DEBUG("@@STGC@@ pair fit isStrip= " << isStrip << " slope= " << slopeInTwo[iLayer].at(iPair) << " intercept= " << interceptInTwo[iLayer].at(iPair));
518 }
519 }
520
521 std::array<std::vector<unsigned long int>,2> hitIdsInFour;
522 std::array<std::vector<double>,2> slopeInFour;
523 std::array<std::vector<double>,2> interceptInFour;
524 for(unsigned int iQuad = 0; iQuad < 2; ++iQuad){
525 unsigned int nPairsInInner = hitIdsInTwo[iQuad].size();
526 unsigned int nPairsInOuter = hitIdsInTwo[iQuad+2].size();
527 //coverity[STACK_USE]
528 std::array<bool, 0xffff> foundCounterparts{};
529 for(unsigned int iPair = 0; iPair < nPairsInInner; ++iPair){
530 bool foundCounterpart = 0;
531 double slope[2];
532 double intercept[2];
533 slope[0] = slopeInTwo[iQuad].at(iPair);
534 intercept[0] = interceptInTwo[iQuad].at(iPair);
535
536 for(unsigned int jPair = 0; jPair < nPairsInOuter; ++jPair){
537 unsigned int ihitIds = hitIdsInTwo[iQuad].at(iPair);
538 unsigned int jhitIds = hitIdsInTwo[iQuad+2].at(jPair);
539 if ( !(((ihitIds>>16 & 0xffff) != 0xffff || (ihitIds & 0xffff) != 0xffff) &&
540 ((jhitIds>>16 & 0xffff) != 0xffff || (jhitIds & 0xffff) != 0xffff )) ) continue; // require at least 2 hits in 4 layers
541
542 slope[1] = slopeInTwo[iQuad+2].at(jPair);
543 intercept[1] = interceptInTwo[iQuad+2].at(jPair);
544
545 if (isStrip) {
546 double spR0 = slope[0] * NSWCenterZ + intercept[0];
547 double spR1 = slope[1] * NSWCenterZ + intercept[1];
548 if(std::abs(spR1 - spR0) > 50.) continue; //OPTIMIZE ME!!!
549 } else {
550 if(std::abs(intercept[0]*std::sin(slope[0]) - intercept[1]*std::sin(slope[1])) > 100.) continue;
551 }
552
553 foundCounterpart = 1;
554 foundCounterparts[jPair] = 1;
555
556 unsigned long int encodedIds = (hitIdsInTwo[iQuad].at(iPair) << 32 ) + hitIdsInTwo[iQuad+2].at(jPair);
557 hitIdsInFour[iQuad].push_back(encodedIds);
558 slopeInFour[iQuad].push_back((slope[1] + slope[0])/2.);
559 interceptInFour[iQuad].push_back((intercept[1] + intercept[0])/2.);
560 }// end of iPair of the i-th and (i+4)-th layers, i=0,2
561
562 if(foundCounterpart) continue; // in case of no counterpart of pairs in the inner layers
563 if((hitIdsInTwo[iQuad].at(iPair)>>16 & 0xffff) == 0xffff || (hitIdsInTwo[iQuad].at(iPair) & 0xffff) == 0xffff) continue;
564
565 unsigned long int encodedIds = (hitIdsInTwo[iQuad].at(iPair) << 32 ) + 0xffffffff;
566 hitIdsInFour[iQuad].push_back(encodedIds);
567 slopeInFour[iQuad].push_back(slope[0]);
568 interceptInFour[iQuad].push_back(intercept[0]);
569 }// end of jPair of the j-th and (j+4)-th layers, j=1,3
570 for (unsigned int jPair = 0; jPair < nPairsInOuter; ++jPair) {
571 if(foundCounterparts[jPair]) continue; // in case of no counterpart of pairs in the outner layers
572 if((hitIdsInTwo[iQuad+2].at(jPair)>>16 & 0xffff) == 0xffff || (hitIdsInTwo[iQuad+2].at(jPair) & 0xffff) == 0xffff) continue;
573// unsigned long int encodedIds = (0xffffffff << 32) + hitIdsInTwo[iQuad+2].at(jPair);
574 unsigned long int encodedIds = (0xffffffff00000000 ) + hitIdsInTwo[iQuad+2].at(jPair);
575 hitIdsInFour[iQuad].push_back(encodedIds);
576 slopeInFour[iQuad].push_back(slopeInTwo[iQuad+2].at(jPair));
577 interceptInFour[iQuad].push_back(interceptInTwo[iQuad+2].at(jPair));
578 }
579 }// end of quad loop
580
581 ATH_MSG_DEBUG("@@STGC@@ isStrip= " << isStrip << " Nquads " << hitIdsInFour[0].size() << " " << hitIdsInFour[1].size());
582 for (unsigned int iLayer = 0; iLayer < 2; ++ iLayer) {
583 for (unsigned int iQuad = 0; iQuad < slopeInFour[iLayer].size(); ++iQuad) {
584 ATH_MSG_DEBUG("@@STGC@@ quad fit isStrip= " << isStrip << " slope= " << slopeInFour[iLayer].at(iQuad) << " intercept= " << interceptInFour[iLayer].at(iQuad));
585 }
586 }
587
588 std::vector< std::array<int, 8> > hitIdsInEight;
589 std::vector<double> mseInEight;
590
591 unsigned int nQuadInInner = hitIdsInFour[0].size();
592 unsigned int nQuadInOuter = hitIdsInFour[1].size();
593
594 for(unsigned int iQuad = 0; iQuad < nQuadInInner; ++iQuad){
595 double slope[2];
596 double intercept[2];
597 slope[0] = slopeInFour[0].at(iQuad);
598 intercept[0] = interceptInFour[0].at(iQuad);
599
600 for(unsigned int jQuad = 0; jQuad < nQuadInOuter; ++jQuad){
601 unsigned long int ihitIds = hitIdsInFour[0].at(iQuad);
602 unsigned long int jhitIds = hitIdsInFour[1].at(jQuad);
603 int nOfLayersWithNoHit = 0;
604 for (unsigned int iLayer = 0; iLayer < 4; ++iLayer) {
605 if ( (ihitIds>>(3-iLayer)*16 & 0xffff) == 0xffff ) {++nOfLayersWithNoHit;}
606 if ( (jhitIds>>(3-iLayer)*16 & 0xffff) == 0xffff ) {++nOfLayersWithNoHit;}
607 }
608 if (nOfLayersWithNoHit > 4) continue; // require at least 4 hits in 8 layers
609
610 slope[1] = slopeInFour[1].at(jQuad);
611 intercept[1] = interceptInFour[1].at(jQuad);
612
613 if(isStrip) {
614 double spR0 = slope[0] * NSWCenterZ + intercept[0];
615 double spR1 = slope[1] * NSWCenterZ + intercept[1];
616 if(std::abs(spR1 - spR0) > 10. ||
617 std::abs(intercept[1] + intercept[0]) / 2 > 100.) continue; // OPTIMIZE ME!!!
618 } else {
619 if(std::abs(intercept[0]*std::sin(slope[0]) - intercept[1]*std::sin(slope[1])) > 100. ) continue;
620 }
621
622 std::array<int,8> setOfHitIds = {-1,-1,-1,-1,-1,-1,-1,-1};
623 std::vector<double> r, z;
624 for(unsigned int i = 0; i < 8; ++i) {
625 unsigned int iHitId, iLayer = 0;
626 if (i <= 3) {
627 iHitId = (unsigned int) ((ihitIds>>(3-i)*16) & 0xffff);
628 iLayer = i+3*(i%2);
629 } else {
630 iHitId = (unsigned int) ((jhitIds>>(3-i%4)*16) & 0xffff);
631 iLayer = (i-4)+3*(i%2)+1;
632 }
633 if ( iHitId != 0xffff ) {
634 if (isStrip) {
635 r.push_back(stgcHits.at(iHitId).r);
636 z.push_back(stgcHits.at(iHitId).z);
637 }
638 else {
639 double localPhiCenter;
640 if (stgcHits.at(iHitId).stationPhi<=5) {
641 localPhiCenter = 0.25 * M_PI * ((double)stgcHits.at(iHitId).stationPhi-1.);
642 } else {
643 localPhiCenter = 0.25 * M_PI * ((double)stgcHits.at(iHitId).stationPhi-9.);
644 }
645 if (stgcHits.at(iHitId).stationName == 57){
646 localPhiCenter += M_PI/8.; // small sTGC sectors
647 if (stgcHits.at(iHitId).stationPhi == 5) localPhiCenter -= 2 * M_PI;
648 }
649
650 double phiProj = stgcHits.at(iHitId).phi - localPhiCenter;
651 if (phiProj > M_PI) phiProj -= 2.0*M_PI;
652 if (phiProj < -1.*M_PI) phiProj += 2.0*M_PI;
653 r.push_back(phiProj);
654 z.push_back(stgcHits.at(iHitId).r);
655 }
656 setOfHitIds[iLayer] = iHitId;
657 ATH_MSG_DEBUG("@@STGC@@ strip_pos iHitId " << iLayer << " " << iHitId);
658 }
659 }
660 double slopefit=0., interceptfit=99999., mse =-1.;
661 if (isStrip) {
662 LinearFit(z,r,&slopefit,&interceptfit,&mse);
663 } else {
664 double phiavg = 0.;
665 for (unsigned int iHit = 0; iHit < r.size(); ++iHit){
666 phiavg += r.at(iHit);
667 }
668 phiavg /= r.size();
669 mse = 0.;
670 for (unsigned int iHit = 0; iHit < r.size(); ++iHit){
671 mse += std::pow(r.at(iHit) - phiavg,2);
672 }
673 }
674 hitIdsInEight.push_back(setOfHitIds);
675 mseInEight.push_back(mse);
676 } // end of quad loop in the outer layers
677 } // end of quad loop in the inner layers
678 if(!hitIdsInEight.size()){
679 ATH_MSG_DEBUG("No candidate segment found in STGC");
680 return;
681 }
682
683 ATH_MSG_DEBUG("@@STGC@@ isStrip= " << isStrip << " Noctets " << hitIdsInEight.size());
684 std::vector<int> nOctetSegments;
685 std::vector<int> patternStationName;
686
687 for (unsigned int iOctet = 0; iOctet < hitIdsInEight.size(); ++iOctet) {
688
689 bool isFirstHit = true;
690 int hitStationName = 0;
691
692 int nOctetSegment = 0;
693 ATH_MSG_DEBUG("@@STGC@@ octet fit isStrip= " << isStrip << " mse " << mseInEight.at(iOctet));
694 std::array<int, 8> tmpOctet = hitIdsInEight.at(iOctet);
695 for (unsigned int iLayer = 0; iLayer < 8; ++iLayer) {
696 if (tmpOctet[iLayer] != -1) {
697
698 if(isFirstHit){
699 hitStationName = stgcHits.at(tmpOctet[iLayer]).stationName;
700 isFirstHit = false;
701
702 ATH_MSG_DEBUG("@@STGC@@ octet pos isStrip= " << isStrip << " r= " << stgcHits.at(tmpOctet[iLayer]).r << " phi= " << stgcHits.at(tmpOctet[iLayer]).phi << " z= " << stgcHits.at(tmpOctet[iLayer]).z);
703 nOctetSegment++;
704 }
705 else if(stgcHits.at(tmpOctet[iLayer]).stationName == hitStationName){
706 ATH_MSG_DEBUG("@@STGC@@ octet pos isStrip= " << isStrip << " r= " << stgcHits.at(tmpOctet[iLayer]).r << " phi= " << stgcHits.at(tmpOctet[iLayer]).phi << " z= " << stgcHits.at(tmpOctet[iLayer]).z);
707 nOctetSegment++;
708 }
709 }
710 }
711 nOctetSegments.push_back(nOctetSegment);
712 patternStationName.push_back(hitStationName);
713 }
714 double nOcSegMax = 0;
715 for(unsigned int iOctet = 0; iOctet < hitIdsInEight.size(); ++iOctet){
716 if(nOctetSegments.at(iOctet) > nOcSegMax){
717 nOcSegMax = nOctetSegments.at(iOctet);
718 }
719 }
720
721 double msemin = 1000000.;
722 double mseminWireL = 1000000.; // Large sector
723 double mseminWireS = 1000000.; // Small sector
724
725 std::vector<int> octetIds(2,-1);
726
727 if(isStrip){
728 for(unsigned int iOctet = 0; iOctet < hitIdsInEight.size(); ++iOctet){
729 if(nOctetSegments.at(iOctet) != nOcSegMax){
730 continue;
731 }
732 if( mseInEight.at(iOctet) < msemin) {
733 msemin = mseInEight.at(iOctet);
734 }
735 }// end of Octet loop
736 for(unsigned int iOctet = 0; iOctet < hitIdsInEight.size(); ++iOctet){
737 if(nOctetSegments.at(iOctet) != nOcSegMax) continue;
738 if(mseInEight.at(iOctet) != msemin){
739 continue;
740 }
741 octetIds.push_back(iOctet);
742 }
743 } else {
744 for(unsigned int iOctet = 0; iOctet < hitIdsInEight.size(); ++iOctet){
745 if(patternStationName.at(iOctet) == 58){
746 if( mseInEight.at(iOctet) < mseminWireL) {
747 mseminWireL = mseInEight.at(iOctet);
748 }
749 }
750 else if(patternStationName.at(iOctet) == 57){
751 if( mseInEight.at(iOctet) < mseminWireS) {
752 mseminWireS = mseInEight.at(iOctet);
753 }
754 }
755 }// end of Octet loop
756 for(unsigned int iOctet = 0; iOctet < hitIdsInEight.size(); ++iOctet){
757 if(patternStationName.at(iOctet) == 58){
758 if(mseInEight.at(iOctet) != mseminWireL){
759 continue;
760 }
761 }
762 else if(patternStationName.at(iOctet) == 57){
763 if(mseInEight.at(iOctet) != mseminWireS){
764 continue;
765 }
766 }
767 octetIds.push_back(iOctet);
768 }
769 }
770 for(unsigned int ids = 0; ids < octetIds.size(); ids++){
771 if (octetIds.at(ids) != -1) {
772 hitIdsCandidate.push_back(hitIdsInEight.at(octetIds.at(ids)));
773 }
774 }
775}
776
778 TrigL2MuonSA::StgcHits& stgcHits) const
779{
780 TrigL2MuonSA::StgcHits selectedStgcHits;
781 selectedStgcHits.clear();
782 if(stgcHits.size() == 0) return StatusCode::SUCCESS;
783 for(unsigned int iHit = 0; iHit < stgcHits.size(); iHit++){
784 if(stgcHits.at(iHit).isOutlier != 0) continue;
785 selectedStgcHits.push_back(stgcHits.at(iHit));
786 }
787 trackPattern.stgcSegment.clear();
788 trackPattern.stgcSegment = std::move(selectedStgcHits);
789 return StatusCode::SUCCESS;
790}
792 TrigL2MuonSA::MmHits& mmHits) const
793{
794 TrigL2MuonSA::MmHits selectedMmHits;
795 selectedMmHits.clear();
796 if(mmHits.size() == 0) return StatusCode::SUCCESS;
797 for(unsigned int iHit = 0; iHit < mmHits.size(); iHit++){
798 if(mmHits.at(iHit).isOutlier != 0) continue;
799 selectedMmHits.push_back(mmHits.at(iHit));
800 }
801 trackPattern.mmSegment.clear();
802 trackPattern.mmSegment = std::move(selectedMmHits);
803 return StatusCode::SUCCESS;
804}
805
806
807void TrigL2MuonSA::NswStationFitter::LinearFit(std::vector<double>& x,std::vector<double>& y,
808 double* slope, double* intercept, double* mse) const
809{
810 double sumX=0, sumY=0, sumXY=0, sumX2=0;
811 int nHits = x.size();
812 *mse = 0.;
813 for (unsigned int iHit = 0; iHit < x.size(); ++iHit){
814 sumX += x.at(iHit);
815 sumY += y.at(iHit);
816 sumXY += x.at(iHit)*y.at(iHit);
817 sumX2 += x.at(iHit)*x.at(iHit);
818 }
819
820 if(nHits > 1) {
821 if(nHits * sumX2 - (sumX * sumX) > ZERO_LIMIT) {
822 *slope = (nHits * sumXY - sumX * sumY) / (nHits * sumX2 - (sumX * sumX));
823 *intercept = (sumX2 * sumY - sumXY * sumX) / (nHits * sumX2 - sumX * sumX);
824 } else {
825 *slope = 0.;
826 *intercept = sumY/nHits;
827 }
828 }
829 else if(nHits == 1) {
830 if (sumX == 0.)[[unlikely]]{
831 throw std::runtime_error("NswStationFitter::LinearFit: divisor is zero.");
832 }
833 *slope = sumY/sumX;
834 *intercept = 0.;
835 }
836
837 if(nHits > 2) {
838 for(unsigned int iHit = 0; iHit< x.size(); ++iHit){
839 *mse += std::pow(y.at(iHit) - (*slope * x.at(iHit) + *intercept), 2.0);
840 }
841 *mse = *mse / (nHits - 2);
842 }
843 else {
844 *mse = 1000.;
845 }
846}
847
848void TrigL2MuonSA::NswStationFitter::LinearFitWeight(std::vector<double>& x,std::vector<double>& y,
849 std::vector<bool>& isStgc, double* slope, double* intercept, double* mse, double eta) const
850{
851 double RmsDeltarEtaStgc[12] = {};
852 double RmsDeltarEtaMm[12]= {};
853 getNswResolution(RmsDeltarEtaStgc, RmsDeltarEtaMm, 12);
854
855 double weightStgc[12] = {};
856 double weightMm[12] = {};
857 for(int i_weight=0; i_weight<12; i_weight++){
858 weightStgc[i_weight] = 1/std::pow(RmsDeltarEtaStgc[i_weight],2);
859 weightMm[i_weight] = 1/std::pow(RmsDeltarEtaMm[i_weight],2);
860 }
861 int weightBin = 0;
862 double minEta = 1.3;
863 double maxEta = 1.4;
864 for(int iBin=0; iBin<12; iBin++){
865 if(std::abs(eta) >= minEta && std::abs(eta) < maxEta){
866 weightBin = iBin;
867 break;
868 } else {
869 minEta += 0.1;
870 maxEta += 0.1;
871 }
872 }
873
874 double sumX=0, sumY=0, sumXY=0, sumX2=0, sumW=0;
875 int nHits = x.size();
876 *mse = 0.;
877 for (unsigned int iHit = 0; iHit < x.size(); ++iHit){
878 if(isStgc.at(iHit)){
879 sumX += weightStgc[weightBin] * x.at(iHit);
880 sumY += weightStgc[weightBin] * y.at(iHit);
881 sumXY += weightStgc[weightBin] * x.at(iHit) * y.at(iHit);
882 sumX2 += weightStgc[weightBin] * x.at(iHit) * x.at(iHit);
883 sumW += weightStgc[weightBin];
884 } else {
885 sumX += weightMm[weightBin] * x.at(iHit);
886 sumY += weightMm[weightBin] * y.at(iHit);
887 sumXY += weightMm[weightBin] * x.at(iHit) * y.at(iHit);
888 sumX2 += weightMm[weightBin] * x.at(iHit) * x.at(iHit);
889 sumW += weightMm[weightBin];
890 }
891 }
892
893 if(nHits > 1) {
894 if(nHits * sumX2 - (sumX * sumX) > ZERO_LIMIT) {
895 *slope = (sumW * sumXY - sumX * sumY) / (sumW * sumX2 - (sumX * sumX));
896 *intercept = (sumX2 * sumY - sumXY * sumX) / (sumW * sumX2 - sumX * sumX);
897 } else {
898 *slope = 0.;
899 *intercept = sumY/nHits;
900 }
901 }
902 else if(nHits == 1) {
903 if (sumX == 0.)[[unlikely]]{
904 throw std::runtime_error("NswStationFitter::LinearFitWeight: divisor is zero.");
905 }
906 *slope = sumY/sumX;
907 *intercept = 0.;
908 }
909
910 if(nHits > 2) {
911 for(unsigned int iHit = 0; iHit< x.size(); ++iHit){
912 *mse += std::pow((y.at(iHit) - (*slope * x.at(iHit) + *intercept)), 2.0);
913 }
914 *mse = *mse / (nHits - 2);
915 }
916 else {
917 *mse = 1000.;
918 }
919}
920
921void TrigL2MuonSA::NswStationFitter::getNswResolution(double *stgcDeltaR, double *mmDeltaR, unsigned int size) const
922{
923 double RmsDeltarEtaStgc[12] = {1.43,1.53,1.53,1.56,1.59,1.54,1.70,1.69,1.76,1.81,1.83,1.84};
924 double RmsDeltarEtaMm[12] = {0.49,0.46,0.48,0.40,0.39,0.39,0.38,0.35,0.36,0.33,0.33,0.40};
925 for(unsigned int bin=0; bin < size; bin++){
926 stgcDeltaR[bin] = RmsDeltarEtaStgc[bin];
927 mmDeltaR[bin] = RmsDeltarEtaMm[bin];
928 }
929}
930
932{
933 TrigL2MuonSA::StgcHits stgcHits = trackPattern.stgcSegment;
934 TrigL2MuonSA::MmHits mmHits = trackPattern.mmSegment;
935
936 double side_mm = 0;
937 std::vector<double> r, z;
938 std::vector<bool> isStgc;
939 for(unsigned int iHit = 0; iHit < stgcHits.size(); ++iHit) {
940 if (stgcHits.at(iHit).channelType == 1) {
941 r.push_back(stgcHits.at(iHit).r);
942 z.push_back(stgcHits.at(iHit).z);
943 isStgc.push_back(true);
944 }
945 }
946 for(unsigned int iHit = 0; iHit < mmHits.size(); ++iHit) {
947 if (mmHits.at(iHit).layerNumber < 2 || mmHits.at(iHit).layerNumber > 5) {
948 r.push_back(mmHits.at(iHit).r);
949 z.push_back(mmHits.at(iHit).z);
950 isStgc.push_back(false);
951 side_mm = std::abs(mmHits.at(iHit).z)/mmHits.at(iHit).z;
952 }
953 }
954 double slopefit=0., interceptfit=99999., mse=-1.;
955 LinearFit(z,r,&slopefit,&interceptfit,&mse);
956 ATH_MSG_DEBUG("@@Merge@@ stgc_mmX_fit slope= " << slopefit);
957 ATH_MSG_DEBUG("@@Merge@@ stgc_mmX_fit intercept= " << interceptfit);
958 ATH_MSG_DEBUG("@@Merge@@ stgc_mmX_fit mse= " << mse);
959
960 std::vector<double> phiLocal;
961 double localPhiCenter = 3.*M_PI;
962 for (unsigned int iHit = 0; iHit < stgcHits.size(); ++iHit) {
963 if (stgcHits.at(iHit).channelType != 2) {continue;}
964 if (stgcHits.at(iHit).stationPhi<=5) {
965 localPhiCenter = 0.25 * M_PI * ((double)stgcHits.at(iHit).stationPhi-1.);
966 } else {
967 localPhiCenter = 0.25 * M_PI * ((double)stgcHits.at(iHit).stationPhi-9.);
968 }
969
970 if (stgcHits.at(iHit).stationName == 57){
971 localPhiCenter += M_PI/8.; // small sTGC sectors
972 if (stgcHits.at(iHit).stationPhi == 5) localPhiCenter -= 2. * M_PI;
973 }
974
975 double phiProj = stgcHits.at(iHit).phi - localPhiCenter;
976 if (phiProj > M_PI) phiProj -= 2.0*M_PI;
977 if (phiProj < -1.*M_PI) phiProj += 2.0*M_PI;
978 double rInterpolate = slopefit * stgcHits.at(iHit).z + interceptfit;
979 double rProj = stgcHits.at(iHit).r;
980 phiLocal.push_back( std::atan(rProj/rInterpolate*std::tan(phiProj)) );
981 ATH_MSG_DEBUG("@@Merge@@ philocalwire " << stgcHits.at(iHit).stationPhi << " " << stgcHits.at(iHit).stationName << " "
982 << localPhiCenter << " " << stgcHits.at(iHit).phi << " " << stgcHits.at(iHit).r << " " << stgcHits.at(iHit).z);
983 ATH_MSG_DEBUG("@@Merge@@ philocalwire " << rProj << " " << rInterpolate << " " << std::tan(phiProj) );
984 ATH_MSG_DEBUG("@@Merge@@ philocalwire " << std::atan(rProj/rInterpolate*std::tan(phiProj)) );
985 }
986 double tanTiltAngleU = 0,
987 tanTiltAngleV = 0;
988 double cosTiltAngleU = 0,
989 cosTiltAngleV = 0;
990 double sinTiltAngleU = 0,
991 sinTiltAngleV = 0;
992 if(side_mm > ZERO_LIMIT){
993 tanTiltAngleU = TanM1p5,
994 tanTiltAngleV = TanP1p5;
995 cosTiltAngleU = CosM1p5,
996 cosTiltAngleV = CosP1p5;
997 sinTiltAngleU = SinM1p5,
998 sinTiltAngleV = SinP1p5;
999 } else if(side_mm < -1.*ZERO_LIMIT){
1000 tanTiltAngleU = TanP1p5,
1001 tanTiltAngleV = TanM1p5;
1002 cosTiltAngleU = CosP1p5,
1003 cosTiltAngleV = CosM1p5;
1004 sinTiltAngleU = SinP1p5,
1005 sinTiltAngleV = SinM1p5;
1006 } else {
1007 ATH_MSG_DEBUG("@@Merge@@ no U, V layer hits -> not consider tilt of U/V layers");
1008 }
1009 for (unsigned int iHit = 0; iHit < mmHits.size(); ++iHit) {
1010 if (localPhiCenter > 2.*M_PI) {
1011 if (mmHits.at(iHit).stationPhi<=5) {
1012 localPhiCenter = 0.25 * M_PI * ((double)mmHits.at(iHit).stationPhi-1.);
1013 } else {
1014 localPhiCenter = 0.25 * M_PI * ((double)mmHits.at(iHit).stationPhi-9.);
1015 }
1016 if (mmHits.at(iHit).stationName == 55){
1017 localPhiCenter += M_PI/8.; // small MM sectors
1018 if (mmHits.at(iHit).stationPhi == 5) localPhiCenter -= 2 * M_PI;
1019 }
1020 }
1021 if (mmHits.at(iHit).layerNumber >1 && mmHits.at(iHit).layerNumber < 6){
1022 double rInterpolate = slopefit * mmHits.at(iHit).z + interceptfit;
1023 if (rInterpolate == 0. or tanTiltAngleU == 0.)[[unlikely]]{
1024 throw std::runtime_error("NswStationFitter::calcMergedHit: divisor is zero.");
1025 }
1026 double rProj = mmHits.at(iHit).r;
1027 if(std::abs(side_mm) < ZERO_LIMIT) {
1028 phiLocal.push_back(0);
1029 ATH_MSG_DEBUG("@@Merge@@ philocalmm 0");
1030 }
1031 else if ((mmHits.at(iHit).layerNumber)%2 == 0) { // layer U
1032 phiLocal.push_back( std::atan((rProj-rInterpolate)/tanTiltAngleU/rInterpolate));
1033 ATH_MSG_DEBUG("@@Merge@@ philocalmmU " << std::atan((rProj-rInterpolate)/tanTiltAngleU/rInterpolate));
1034 } else { // layer V
1035 phiLocal.push_back( std::atan((rProj-rInterpolate)/tanTiltAngleV/rInterpolate));
1036 ATH_MSG_DEBUG("@@Merge@@ philocalmmV " << std::atan((rProj-rInterpolate)/tanTiltAngleV/rInterpolate));
1037 }
1038 }
1039 }
1040 double sumPhiLocal = 0;
1041 for (unsigned int iHit = 0; iHit < phiLocal.size(); ++iHit ) {
1042 sumPhiLocal += phiLocal.at(iHit);
1043 }
1044 double phiLocalAvg = sumPhiLocal/phiLocal.size();
1045 ATH_MSG_DEBUG("@@Merge@@ philocalAvg " << phiLocalAvg);
1046
1047 r.clear();
1048 z.clear();
1049 isStgc.clear();
1050 std::vector<double> r_stgc, z_stgc, r_mm, z_mm;
1051 std::vector<bool> isStgc_stgc, isStgc_mm;
1052 double side_stgc = 0;
1053 for(unsigned int iHit = 0; iHit < stgcHits.size(); ++iHit) {
1054 if (stgcHits.at(iHit).stationPhi<=5) localPhiCenter = 0.25 * M_PI * ((double)stgcHits.at(iHit).stationPhi-1.);
1055 if (stgcHits.at(iHit).stationPhi> 5) localPhiCenter = 0.25 * M_PI * ((double)stgcHits.at(iHit).stationPhi-9.);
1056 if (stgcHits.at(iHit).channelType == 1) {
1057 r_stgc.push_back(stgcHits.at(iHit).r/std::cos(phiLocalAvg));
1058 z_stgc.push_back(stgcHits.at(iHit).z);
1059 isStgc_stgc.push_back(true);
1060 side_stgc = std::abs(stgcHits.at(iHit).z)/stgcHits.at(iHit).z;
1061
1062 ATH_MSG_DEBUG("@@Merge@@ stgc strip_r " << phiLocalAvg << " " << stgcHits.at(iHit).z << " " << stgcHits.at(iHit).r/std::cos(phiLocalAvg));
1063 }
1064
1065 }
1066 double slopefit_stgc=0., interceptfit_stgc=99999., mse_stgc=1.e20;
1067 if(r_stgc.size() == 0) {
1068 ATH_MSG_DEBUG("No STGC hit to calculate superoint");
1069 } else {
1070 LinearFit(z_stgc,r_stgc,&slopefit_stgc,&interceptfit_stgc,&mse_stgc);
1071 }
1072
1073 for(unsigned int iHit = 0; iHit < mmHits.size(); ++iHit) {
1074 if (mmHits.at(iHit).layerNumber < 2 || mmHits.at(iHit).layerNumber > 5) {
1075 r_mm.push_back(mmHits.at(iHit).r/std::cos(phiLocalAvg));
1076 z_mm.push_back(mmHits.at(iHit).z);
1077 isStgc_mm.push_back(false);
1078 } else {
1079 z_mm.push_back(mmHits.at(iHit).z);
1080 isStgc_mm.push_back(false);
1081
1082 double rProj = mmHits.at(iHit).r;
1083 if(std::abs(side_mm) < ZERO_LIMIT) { // no layer U/V
1084 r_mm.push_back(rProj);
1085 }
1086 else if ((mmHits.at(iHit).layerNumber)%2 == 0) { // layer U
1087 double rPrime = (rProj * cosTiltAngleU)/(cos(phiLocalAvg)*cosTiltAngleU + sin(phiLocalAvg)*sinTiltAngleU);
1088 r_mm.push_back(rPrime);
1089 } else { //layer V
1090 double rPrime = (rProj * cosTiltAngleV)/(cos(phiLocalAvg)*cosTiltAngleV + sin(phiLocalAvg)*sinTiltAngleV);
1091 r_mm.push_back(rPrime);
1092 }
1093 }
1094 }
1095 double slopefit_mm=0., interceptfit_mm=99999., mse_mm=1.e20;
1096 if(r_mm.size() == 0) {
1097 ATH_MSG_WARNING("No MM hit to calculate superoint");
1098 } else {
1099 LinearFit(z_mm,r_mm,&slopefit_mm,&interceptfit_mm,&mse_mm);
1100 }
1101
1102 unsigned int fmerge = 0;
1103 slopefit=0., interceptfit=99999., mse=1.e20;
1104 double side = 0;
1105 double StgcSegZ = 7526.329;
1106 double StgcSegR = 0;
1107 double MmSegZ = 7526.329;
1108 double MmSegR = 0;
1109 if (mse_stgc < 1.e7 && mse_mm < 1.e7) {
1110 r = r_stgc;
1111 copy(r_mm.begin(), r_mm.end(), back_inserter(r));
1112 z = z_stgc;
1113 copy(z_mm.begin(), z_mm.end(), back_inserter(z));
1114 isStgc = isStgc_stgc;
1115 copy(isStgc_mm.begin(), isStgc_mm.end(), back_inserter(isStgc));
1116
1117 if(side_stgc < -1.*ZERO_LIMIT){
1118 StgcSegZ = -7526.329;
1119 }
1120 StgcSegR = slopefit_stgc * StgcSegZ + interceptfit_stgc;
1121 double StgcSegOriginTheta = std::atan(StgcSegR / StgcSegZ);
1122 double StgcSegEta = side_stgc * (- std::log(std::abs(std::tan(StgcSegOriginTheta / 2))));
1123 if(side_mm < -1.*ZERO_LIMIT){
1124 MmSegZ = -7526.329;
1125 }
1126 MmSegR = slopefit_mm * MmSegZ + interceptfit_mm;
1127 double MmSegOriginTheta = std::atan(MmSegR / MmSegZ);
1128 double MmSegEta = side_stgc * (- std::log(std::abs(std::tan(MmSegOriginTheta / 2))));
1129
1130 double SegEtaAve = 0;
1131 if(std::abs(side_stgc) > ZERO_LIMIT || std::abs(side_mm) > ZERO_LIMIT){
1132 if(side_stgc*side_mm > 0){
1133 side = side_stgc;
1134 SegEtaAve = (StgcSegEta + MmSegEta)/2;
1135 } else if(std::abs(side_stgc) < ZERO_LIMIT) {
1136 side = side_mm;
1137 SegEtaAve = MmSegEta;
1138 } else if(std::abs(side_mm) < ZERO_LIMIT) {
1139 side = side_stgc;
1140 SegEtaAve = StgcSegEta;
1141 }
1142 }
1143
1144 LinearFitWeight(z,r,isStgc,&slopefit,&interceptfit,&mse,SegEtaAve);
1145 fmerge = 1;
1146 }
1147 if (mse > 1.e7) {
1148 if (mse_stgc < mse_mm) {
1149 slopefit = slopefit_stgc;
1150 interceptfit = interceptfit_stgc;
1151 mse = mse_stgc;
1152 z = std::move(z_stgc);
1153 side = side_stgc;
1154 fmerge = 2;
1155 } else {
1156 slopefit = slopefit_mm;
1157 interceptfit = interceptfit_mm;
1158 mse = mse_mm;
1159 z = std::move(z_mm);
1160 side = side_mm;
1161 fmerge = 3;
1162 }
1163 }
1164 if (mse > 1.e19) {
1165 ATH_MSG_WARNING("No sTGC and MM hit to calculate superoint");
1166 return StatusCode::SUCCESS;
1167 }
1168
1169 // store superpoint info in TrackData
1171 TrigL2MuonSA::SuperPoint* superPoint = &(trackPattern.superPoints[inner]);
1172 double NSWCenterZ = 7526.329;
1173 if(side < -1.*ZERO_LIMIT){
1174 NSWCenterZ = -7526.329;
1175 }
1176 superPoint->R = slopefit * NSWCenterZ + interceptfit;
1177 superPoint->Phim = phiLocalAvg+localPhiCenter;
1178 superPoint->Z = NSWCenterZ;
1179 superPoint->Npoint = z.size();
1180
1181 if (NSWCenterZ != 0) superPoint->Alin = slopefit;
1182 superPoint->Blin = interceptfit;
1183
1184 ATH_MSG_DEBUG("Nsw Super Point r/phi/z/slope = "<<superPoint->R<<"/"<<superPoint->Phim<<"/"<<superPoint->Z<<"/"<<superPoint->Alin);
1185
1186 ATH_MSG_DEBUG("@@Merge@@ Nsw Super Point r/phi/z/slope = "<<superPoint->R<<"/"<<superPoint->Phim<<"/"<<superPoint->Z<<"/"<<superPoint->Alin);
1187 ATH_MSG_DEBUG("@@Merge@@ fit slope= " << slopefit << " " << slopefit_stgc << " " << slopefit_mm);
1188 ATH_MSG_DEBUG("@@Merge@@ fit intercept= " << interceptfit << " " << interceptfit_stgc << " " << interceptfit_mm);
1189 ATH_MSG_DEBUG("@@Merge@@ fit mse= " << mse << " " << mse_stgc << " " << mse_mm);
1190 ATH_MSG_DEBUG("@@Merge@@ fit tech= " << fmerge);
1191
1192
1193 return StatusCode::SUCCESS;
1194
1195}
1196
1198{
1199 if(mmHits.size() == 0) return StatusCode::SUCCESS;
1200 int hitsInRoad = 0;
1201 for(unsigned int iHit = 0; iHit < mmHits.size(); iHit++){
1202 if(mmHits.at(iHit).isOutlier == 0){
1203 hitsInRoad++;
1204 mmHits.at(iHit).isOutlier = 1;
1205 }
1206 }
1207 if(hitsInRoad == 0) return StatusCode::SUCCESS;
1208
1209 if(hitsInRoad < 6) {
1210 ATH_MSG_DEBUG("Number of MM hits is too small, at least 6 hits required : "<<hitsInRoad<<" hits");
1211 return StatusCode::SUCCESS;
1212 } else if(hitsInRoad > 100) {
1213 ATH_MSG_WARNING("Number of MM hits is too large, at most (2^16 - 1) hits allowed : "<<hitsInRoad<<" hits");
1214 return StatusCode::SUCCESS;
1215 }
1216
1217 std::array< std::vector<int>, 8 > hitIdByLayer;
1218 for(unsigned int iHit = 0; iHit < mmHits.size(); ++iHit){
1219 if(mmHits.at(iHit).isOutlier != 1) continue;
1220 int layerNumber = mmHits.at(iHit).layerNumber;
1221 if (layerNumber > 7) {
1222 ATH_MSG_WARNING("MM hit layer number > 7");
1223 continue;
1224 }
1225 hitIdByLayer[layerNumber].push_back(iHit);
1226 }
1227 ATH_MSG_DEBUG("@@MM@@ Nhits " << hitIdByLayer[0].size()
1228 << " " << hitIdByLayer[1].size()
1229 << " " << hitIdByLayer[2].size()
1230 << " " << hitIdByLayer[3].size()
1231 << " " << hitIdByLayer[4].size()
1232 << " " << hitIdByLayer[5].size()
1233 << " " << hitIdByLayer[6].size()
1234 << " " << hitIdByLayer[7].size());
1235
1236 std::vector< std::array<int, 8> > mmHitIds;
1237 findSetOfMmHitIds(mmHits, hitIdByLayer, mmHitIds);
1238 for (unsigned int iHit = 0; iHit < mmHitIds.size(); ++iHit) {
1239 std::array<int, 8> hitIds = mmHitIds.at(iHit);
1240 for (unsigned int iLayer = 0; iLayer < 8; ++iLayer) {
1241 if (hitIds[iLayer] != -1) {
1242 mmHits.at(hitIds[iLayer]).isOutlier = 0;
1243 }
1244 }
1245 }
1246 return StatusCode::SUCCESS;
1247}
1248
1250 const std::array<std::vector<int>,8> & hitIdByLayer,
1251 std::vector<std::array<int, 8>>& hitIdsCandidate) const
1252{
1253
1254 double NSWCenterZ = 7526.329;
1255 int side = 0;
1256 for (unsigned int iLayer = 0; iLayer < 8; ++iLayer) {
1257 if ( hitIdByLayer[iLayer].size() > 0) {
1258 side = std::abs(mmHits.at(hitIdByLayer[iLayer].at(0)).z)/mmHits.at(hitIdByLayer[iLayer].at(0)).z;
1259 break;
1260 }
1261 }
1262 NSWCenterZ = NSWCenterZ * side;
1263
1264 std::array<std::vector<unsigned long int>,4> hitIdsInTwo;
1265 std::array<std::vector<double>,4> slopeInTwo;
1266 std::array<std::vector<double>,4> interceptInTwo;
1267 // Loop over pairs of the i-th and the (i+6)-th layers
1268 for(unsigned int iPair = 0; iPair < 4; ++iPair){
1269
1270 unsigned int nHitsInInner = hitIdByLayer[iPair].size();
1271 unsigned int nHitsInOuter;
1272 if (iPair < 2) { // paris of X layers
1273 nHitsInOuter = hitIdByLayer[iPair+6].size();
1274 } else { // pairs of U or V layers
1275 nHitsInOuter = hitIdByLayer[iPair+2].size();
1276 }
1277
1278 if ( nHitsInInner > 0xffff-1 || nHitsInOuter > 0xffff-1) {
1279 ATH_MSG_WARNING("Number of Mm hits in layers exceeds the limit of (2^16 - 1) : Number of Mm hits in "<<iPair<<"th layer = "<< nHitsInInner
1280 <<", Number of Mm hits in "<<iPair+4<<"th layer = "<<nHitsInOuter);
1281 ATH_MSG_WARNING("Number of Mm hits is limitted to (2^16 - 1) and hits with id more than (2^16 -1) will be trancated.");
1282 if (nHitsInInner > 0xffff-1) {nHitsInInner = 0xffff-1;}
1283 if (nHitsInOuter > 0xffff-1) {nHitsInOuter = 0xffff-1;}
1284 }
1285 //coverity[STACK_USE]
1286 std::array<bool, 0xffff> foundCounterparts{};
1287 // Loop over hits in the i-th layer
1288 for(unsigned int iHit = 0; iHit < nHitsInInner; ++iHit){
1289
1290 bool foundCounterpart = 0;
1291
1292 double z[2] = {};
1293 double r[2] = {};
1294
1295 int iHitId = hitIdByLayer[iPair].at(iHit);
1296 r[0] = mmHits.at(iHitId).r;
1297 z[0] = mmHits.at(iHitId).z;
1298
1299 // Loop over hits in the (i+6)-th layer
1300 for(unsigned int jHit = 0; jHit < nHitsInOuter; ++jHit){
1301
1302 int jHitId;
1303 if (iPair < 2) {
1304 jHitId = hitIdByLayer[iPair+6].at(jHit);
1305 } else {
1306 jHitId = hitIdByLayer[iPair+2].at(jHit);
1307 }
1308 r[1] = mmHits.at(jHitId).r;
1309 z[1] = mmHits.at(jHitId).z;
1310
1311 double slope = (r[1] - r[0]) / (z[1] - z[0]);
1312 double intercept = slope*(0. - z[0]) + r[0];
1313 // select pairs whose slops in limited regions
1314 if(std::abs(slope) < 0.1 || std::abs(slope) > 0.7 || std::abs(intercept) > 500.) continue;
1315
1316 int encodedIds = (iHitId<<16) + jHitId;
1317 hitIdsInTwo[iPair].push_back(encodedIds);
1318 slopeInTwo[iPair].push_back(slope);
1319 interceptInTwo[iPair].push_back(intercept);
1320
1321 foundCounterpart = 1;
1322 foundCounterparts[jHit] = 1;
1323 }//end of jHit in the (i+6)-th layer
1324 if(!foundCounterpart){ // in case of no counterpart in the (i+4)-th layer
1325 int encodedIds = (iHitId<<16) + 0xffff; // fill all bits with 1 for hit id for the layer with no hit
1326 hitIdsInTwo[iPair].push_back(encodedIds);
1327 slopeInTwo[iPair].push_back(r[0]/z[0]);
1328 interceptInTwo[iPair].push_back(0.);
1329 }
1330 }//end of iHit in the i-th layer
1331 // Loop over hits in the (i+4)-th layer
1332 for(unsigned int jHit = 0; jHit < nHitsInOuter; ++jHit){
1333 if (!foundCounterparts[jHit]) {
1334 int jHitId;
1335 if (iPair < 2) {
1336 jHitId = hitIdByLayer[iPair+6].at(jHit);
1337 } else {
1338 jHitId = hitIdByLayer[iPair+2].at(jHit);
1339 }
1340 int encodedIds = (0xFFFFu<<16) + jHitId; // fill all bits with 1 for hit id for the layer with no hit
1341 hitIdsInTwo[iPair].push_back(encodedIds);
1342 slopeInTwo[iPair].push_back(mmHits.at(jHitId).r/mmHits.at(jHitId).z);
1343 interceptInTwo[iPair].push_back(0.);
1344 }
1345 }
1346 }//end of pair loop
1347 ATH_MSG_DEBUG("@@MM@@ Npairs " << hitIdsInTwo[0].size() << " " << hitIdsInTwo[1].size() << " " << hitIdsInTwo[2].size() << " " << hitIdsInTwo[3].size());
1348 for (unsigned int iLayer = 0; iLayer < 4; ++ iLayer) {
1349 for (unsigned int iPair = 0; iPair < slopeInTwo[iLayer].size(); ++iPair) {
1350 ATH_MSG_DEBUG("@@MM@@ pair fit slope= " << slopeInTwo[iLayer].at(iPair) << " intercept= " << interceptInTwo[iLayer].at(iPair));
1351 }
1352 }
1353
1354 std::vector<std::array<int, 4>> hitIdsInFourX;
1355 std::vector<double> slopeInFourX;
1356 std::vector<double> interceptInFourX;
1357 std::vector<double> mseInFourX;
1358
1359 unsigned int nPairsInInnerX = hitIdsInTwo[0].size();
1360 unsigned int nPairsInOuterX = hitIdsInTwo[1].size();
1361
1362 for(unsigned int iPairX = 0; iPairX < nPairsInInnerX; ++iPairX){
1363
1364 double slope[2];
1365 double intercept[2];
1366 double spR[2];
1367
1368 slope[0] = slopeInTwo[0].at(iPairX);
1369 intercept[0] = interceptInTwo[0].at(iPairX);
1370 spR[0] = slope[0] * NSWCenterZ + intercept[0];
1371 for(unsigned int jPairX = 0; jPairX < nPairsInOuterX; ++jPairX){
1372 int ihitIds = hitIdsInTwo[0].at(iPairX);
1373 int jhitIds = hitIdsInTwo[1].at(jPairX);
1374 if ( ((ihitIds>>16 & 0xffff) == 0xffff || (ihitIds & 0xffff) == 0xffff) &&
1375 ((jhitIds>>16 & 0xffff) == 0xffff || (jhitIds & 0xffff) == 0xffff )) continue; // require at least 3 hits in 4 layers
1376
1377 slope[1] = slopeInTwo[1].at(jPairX);
1378 intercept[1] = interceptInTwo[1].at(jPairX);
1379 spR[1] = slope[1] * NSWCenterZ + intercept[1];
1380
1381 if(std::abs(spR[1] - spR[0]) > 50. ||
1382 std::abs((intercept[1] + intercept[0]) / 2) > 200.) continue;
1383
1384 std::array<int, 4> setOfHitIds{};
1385 setOfHitIds[0] = (ihitIds>>16 & 0xffff);
1386 setOfHitIds[1] = (ihitIds & 0xffff);
1387 setOfHitIds[2] = (jhitIds>>16 & 0xffff);
1388 setOfHitIds[3] = (jhitIds & 0xffff);
1389 std::vector<double> r;
1390 std::vector<double> z;
1391 for(unsigned int iLayer = 0; iLayer < 4; ++iLayer){
1392 if(setOfHitIds[iLayer] == 0xffff) {
1393 continue;
1394 }
1395 double rhit = mmHits.at(setOfHitIds[iLayer]).r;
1396 double zhit = mmHits.at(setOfHitIds[iLayer]).z;
1397 r.push_back(rhit);
1398 z.push_back(zhit);
1399 }
1400 double slopefit=0., interceptfit=99999., mse=-1.;
1401 LinearFit(z,r,&slopefit, &interceptfit, &mse);
1402
1403 hitIdsInFourX.push_back(setOfHitIds);
1404 slopeInFourX.push_back(slopefit);
1405 interceptInFourX.push_back(interceptfit);
1406 mseInFourX.push_back(mse);
1407
1408 }// end of iPair of the i-th and (i+4)-th layers, i=0,2
1409 }// end of jPair of the j-th and (j+4)-th layers, j=1,3
1410 ATH_MSG_DEBUG("@@MM@@ X Nquads " << hitIdsInFourX.size());
1411 for (unsigned int iQuad = 0; iQuad < slopeInFourX.size(); ++iQuad) {
1412 ATH_MSG_DEBUG("@@MM@@ X quad fit slope= " << slopeInFourX.at(iQuad) << " intercept= " << interceptInFourX.at(iQuad) << " mse= " << mseInFourX.at(iQuad));
1413 }
1414
1415 if(!hitIdsInFourX.size()){
1416 ATH_MSG_WARNING("No candidate segment found in MM X layers");
1417 return;
1418 }
1419
1420 double tanTiltAngleU = 0,
1421 tanTiltAngleV = 0;
1422 if(side > ZERO_LIMIT){
1423 tanTiltAngleU = tan( 1.5/360.*2.*M_PI),
1424 tanTiltAngleV = tan(-1.5/360.*2.*M_PI);
1425 } else if(side < -1.*ZERO_LIMIT){
1426 tanTiltAngleU = tan(-1.5/360.*2.*M_PI),
1427 tanTiltAngleV = tan(1.5/360.*2.*M_PI);
1428 }
1429
1430 std::vector< std::array<int, 8> > hitIdsInEight;
1431 std::vector<double> mseInEight;
1432
1433 for(unsigned int iQuadX = 0; iQuadX < hitIdsInFourX.size(); ++iQuadX){
1434 if(mseInFourX.at(iQuadX) > 10) continue;
1435
1436 double slopeX = slopeInFourX.at(iQuadX);
1437 double interceptX = interceptInFourX.at(iQuadX);
1438 std::array<int,4> hitIdsX{};
1439 hitIdsX = hitIdsInFourX.at(iQuadX);
1440
1441 for (unsigned int iPairU = 0; iPairU < hitIdsInTwo[2].size(); ++iPairU) {
1442
1443 int hitIdsU[2];
1444 hitIdsU[0] = hitIdsInTwo[2].at(iPairU)>>16 & 0xffff;
1445 hitIdsU[1] = hitIdsInTwo[2].at(iPairU) & 0xffff;
1446 double phiLocalU[2]={-99999,-99999};
1447 for(unsigned int iLayer = 0; iLayer < 2; ++iLayer) {
1448 if (hitIdsU[iLayer] == 0xffff) continue;
1449 if (hitIdsU[iLayer] < 0) {
1450 ATH_MSG_DEBUG("@@MM@@ hitIdsU[iLayer] iLayer= " << iLayer << " hitIdsU[iLayer]= " << hitIdsU[iLayer]);
1451 }
1452 double rInterpolate = slopeX * mmHits.at(hitIdsU[iLayer]).z + interceptX;
1453 double rProj = mmHits.at(hitIdsU[iLayer]).r;
1454 if(std::abs(tanTiltAngleU) < ZERO_LIMIT)
1455 phiLocalU[iLayer] = 0;
1456 else
1457 phiLocalU[iLayer] = std::atan((rProj-rInterpolate)/tanTiltAngleU/rInterpolate);
1458 }
1459
1460 for(unsigned int iPairV = 0; iPairV < hitIdsInTwo[3].size(); ++iPairV) {
1461
1462 int hitIdsV[2];
1463 hitIdsV[0] = hitIdsInTwo[3].at(iPairV)>>16 & 0xffff;
1464 hitIdsV[1] = hitIdsInTwo[3].at(iPairV) & 0xffff;
1465
1466 if( (hitIdsU[0] == 0xffff || hitIdsU[1] == 0xffff) &&
1467 (hitIdsV[0] == 0xffff || hitIdsV[1] == 0xffff) ) continue; // require at least 3 UV layers having hits
1468
1469 double phiLocalV[2]={-99999,-99999};
1470 for(unsigned int iLayer = 0; iLayer < 2; ++iLayer) {
1471 if (hitIdsV[iLayer] == 0xffff) continue;
1472 if (hitIdsV[iLayer] < 0) {
1473 ATH_MSG_DEBUG("@@MM@@ hitIdsV[iLayer] iLayer= " << iLayer << " hitIdsV[iLayer]= " << hitIdsV[iLayer]);
1474 }
1475 double rInterpolate = slopeX * mmHits.at(hitIdsV[iLayer]).z + interceptX;
1476 double rProj = mmHits.at(hitIdsV[iLayer]).r;
1477 if(std::abs(tanTiltAngleV) < ZERO_LIMIT)
1478 phiLocalV[iLayer] = 0;
1479 else
1480 phiLocalV[iLayer] = std::atan((rProj-rInterpolate)/tanTiltAngleV/rInterpolate);
1481 }
1482
1483 if ( std::abs(phiLocalU[0]-phiLocalV[0]) > 0.05 &&
1484 std::abs(phiLocalU[1]-phiLocalV[1]) > 0.05) continue;
1485
1486 // average of phis in 4 UV layers
1487 double phiLocalUV = 0;
1488 int nPhi = 0;
1489 for(unsigned int iLayer = 0; iLayer < 2; ++iLayer) {
1490 if(phiLocalU[iLayer] > -99999.) {
1491 phiLocalUV += phiLocalU[iLayer];
1492 ++nPhi;
1493 }
1494 if(phiLocalV[iLayer] > -99999.) {
1495 phiLocalUV += phiLocalV[iLayer];
1496 ++nPhi;
1497 }
1498 }
1499 phiLocalUV /= nPhi;
1500
1501 std::array<int, 8> setOfHitIds = {-1,-1,-1,-1,-1,-1,-1,-1};
1502 std::vector<double> r, z;
1503 for (unsigned int iLayer = 0; iLayer < 4; ++iLayer) {
1504 if ( hitIdsX[iLayer] != 0xffff) {
1505 if (hitIdsX[iLayer] < 0) {
1506 ATH_MSG_DEBUG("@@MM@@ hitIdsX[iLayer] iLayer= " << iLayer << " hitIdsX[iLayer]= " << hitIdsX[iLayer]);
1507 }
1508 z.push_back(mmHits.at(hitIdsX[iLayer]).z);
1509 r.push_back(mmHits.at(hitIdsX[iLayer]).r / std::cos(phiLocalUV));
1510 setOfHitIds[iLayer] = hitIdsX[iLayer];
1511 }
1512 }
1513 for (unsigned int iLayer = 0; iLayer < 2; ++iLayer) {
1514 if ( hitIdsU[iLayer] != 0xffff) {
1515 if (hitIdsU[iLayer] < 0) {
1516 ATH_MSG_DEBUG("@@MM@@ 2 hitIdsU[iLayer] iLayer= " << iLayer << " hitIdsU[iLayer]= " << hitIdsU[iLayer]);
1517 }
1518 z.push_back(mmHits.at(hitIdsU[iLayer]).z);
1519 r.push_back(mmHits.at(hitIdsU[iLayer]).r*(std::cos(phiLocalUV) + 1/std::cos(phiLocalUV))/2.);
1520 setOfHitIds[iLayer+4] = hitIdsU[iLayer];
1521 }
1522 if ( hitIdsV[iLayer] != 0xffff) {
1523 if (hitIdsV[iLayer] < 0) {
1524 ATH_MSG_DEBUG("@@MM@@ 2 hitIdsV[iLayer] iLayer= " << iLayer << " hitIdsV[iLayer]= " << hitIdsV[iLayer]);
1525 }
1526 z.push_back(mmHits.at(hitIdsV[iLayer]).z);
1527 r.push_back(mmHits.at(hitIdsV[iLayer]).r*(std::cos(phiLocalUV) + 1/std::cos(phiLocalUV))/2.);
1528 setOfHitIds[iLayer+6] = hitIdsV[iLayer];
1529 }
1530 }
1531 double slopefit=0., interceptfit=99999., mse=-1.;
1532 LinearFit(z,r,&slopefit,&interceptfit,&mse);
1533
1534 hitIdsInEight.push_back(setOfHitIds);
1535 mseInEight.push_back(mse);
1536 } // end of Pair loop of V layers
1537 } // end of Pair loop of U Layers
1538 }// end of Quad loop of X layers
1539 ATH_MSG_DEBUG("@@MM@@ Noctets " << hitIdsInEight.size());
1540
1541 std::vector<int> nOctetSegments;
1542 std::vector<int> patternStationName;
1543 for (unsigned int iOctet = 0; iOctet < hitIdsInEight.size(); ++iOctet) {
1544 bool isFirstHit = true;
1545 int hitStationName = 0;
1546 int nOctetSegment = 0;
1547 ATH_MSG_DEBUG("@@MM@@ octet fit mse " << mseInEight.at(iOctet));
1548 std::array<int, 8> tmpOctet = hitIdsInEight.at(iOctet);
1549 for (unsigned int iLayer = 0; iLayer < 8; ++iLayer) {
1550 if (tmpOctet[iLayer] != -1) {
1551
1552 if(isFirstHit){
1553 hitStationName = mmHits.at(tmpOctet[iLayer]).stationName;
1554 isFirstHit = false;
1555
1556 ATH_MSG_DEBUG("@@MM@@ octet pos r= " << mmHits.at(tmpOctet[iLayer]).r << " phi= " << mmHits.at(tmpOctet[iLayer]).phi << " z= " << mmHits.at(tmpOctet[iLayer]).z);
1557 nOctetSegment++;
1558 }
1559 else if(mmHits.at(tmpOctet[iLayer]).stationName == hitStationName){
1560 ATH_MSG_DEBUG("@@MM@@ octet pos r= " << mmHits.at(tmpOctet[iLayer]).r << " phi= " << mmHits.at(tmpOctet[iLayer]).phi << " z= " << mmHits.at(tmpOctet[iLayer]).z);
1561 nOctetSegment++;
1562 }
1563
1564 }
1565 }
1566 nOctetSegments.push_back(nOctetSegment);
1567 patternStationName.push_back(hitStationName);
1568 }
1569
1570 double mseminL = 100000.;
1571 double mseminS = 100000.;
1572 std::vector<int> octetIds(2,-1);
1573 for(unsigned int iOctet = 0; iOctet < hitIdsInEight.size(); ++iOctet){
1574 if(patternStationName.at(iOctet) == 56){
1575 if( mseInEight.at(iOctet) < mseminL) {
1576 mseminL = mseInEight.at(iOctet);
1577 }
1578 }
1579 else if(patternStationName.at(iOctet) == 55){
1580 if( mseInEight.at(iOctet) < mseminS) {
1581 mseminS = mseInEight.at(iOctet);
1582 }
1583 }
1584 }// end of Octet loop
1585
1586 for(unsigned int iOctet = 0; iOctet < hitIdsInEight.size(); ++iOctet){
1587 if(patternStationName.at(iOctet) == 56){
1588 if( mseInEight.at(iOctet) != mseminL) {
1589 continue;
1590 }
1591 }
1592 else if(patternStationName.at(iOctet) == 55){
1593 if( mseInEight.at(iOctet) != mseminS) {
1594 continue;
1595 }
1596 }
1597 octetIds.push_back(iOctet);
1598 }
1599
1600 for(unsigned int ids = 0; ids < octetIds.size(); ids++){
1601 if (octetIds.at(ids) != -1) {
1602 hitIdsCandidate.push_back(hitIdsInEight.at(octetIds.at(ids)));
1603 }
1604 }
1605}
#define M_PI
Scalar eta() const
pseudorapidity method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_WARNING(x,...)
bool hit(const Container &ids, int pdgId)
static const double ZERO_LIMIT
static const double SinM1p5
static const double CosP1p5
static const double SinP1p5
static const double TanP1p5
static const double CosM1p5
static const double TanM1p5
static const uint32_t nHits
size_t size() const
Number of registered mappings.
#define y
#define x
#define z
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
virtual double phi() const override final
Methods to retrieve data members.
virtual double eta() const override final
StatusCode findMmHitsInSegment(TrigL2MuonSA::MmHits &mmHits) const
StatusCode calcMergedHit(TrigL2MuonSA::TrackPattern &trackPattern) const
StatusCode MakeSegment(TrigL2MuonSA::TrackPattern &trackPattern, TrigL2MuonSA::StgcHits &stgcHits) const
StatusCode superPointFitter(const TrigRoiDescriptor *p_roids, TrigL2MuonSA::TrackPattern &trackPattern, TrigL2MuonSA::StgcHits &stgcHits, TrigL2MuonSA::MmHits &mmHits) const
void getNswResolution(double *stgcDeltaR, double *mmDeltaR, unsigned int size) const
NswStationFitter(const std::string &type, const std::string &name, const IInterface *parent)
StatusCode findStgcHitsInSegment(TrigL2MuonSA::StgcHits &stgcHits) const
void findSetOfStgcHitIds(TrigL2MuonSA::StgcHits &stgcHits, const std::array< std::vector< int >, 8 > &hitIdByLayer, std::vector< std::array< int, 8 > > &hitIdsCandidate) const
void findSetOfMmHitIds(TrigL2MuonSA::MmHits &mmHits, const std::array< std::vector< int >, 8 > &hitIdByLayer, std::vector< std::array< int, 8 > > &hitIdsCandidate) const
StatusCode selectMmHits(const TrigRoiDescriptor *p_roids, TrigL2MuonSA::MmHits &mmHits) const
StatusCode calcWeightedSumHit(TrigL2MuonSA::TrackPattern &trackPattern) const
void LinearFit(std::vector< double > &x, std::vector< double > &y, double *slope, double *intercept, double *mse) const
StatusCode selectStgcHits(const TrigRoiDescriptor *p_roids, TrigL2MuonSA::StgcHits &stgcHits) const
void LinearFitWeight(std::vector< double > &x, std::vector< double > &y, std::vector< bool > &isStgc, double *slope, double *intercept, double *mse, double eta) const
TrigL2MuonSA::MmHits mmSegment
Definition TrackData.h:58
TrigL2MuonSA::SuperPoint superPoints[s_NCHAMBER]
Definition TrackData.h:60
TrigL2MuonSA::StgcHits stgcSegment
Definition TrackData.h:59
nope - should be used for standalone also, perhaps need to protect the class def bits ifndef XAOD_ANA...
int r
Definition globals.cxx:22
std::vector< StgcHitData > StgcHits
Definition StgcData.h:49
std::vector< MmHitData > MmHits
Definition MmData.h:47
Chamber
Define chamber types and locations.
@ EndcapInner
Inner station in the endcap spectrometer.
#define unlikely(x)