ATLAS Offline Software
Loading...
Searching...
No Matches
TRT_SeededSpacePointFinder_ATL.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6// Implementation file for class TRT_SeededSpacePointFinder_ATL
8// (c) ATLAS Detector software
10// Version 1.0 04/15/2006 T.Koffas
12
13
14#include "GaudiKernel/MsgStream.h"
15#include "GaudiKernel/ServiceHandle.h"
16#include "CLHEP/Vector/ThreeVector.h"
20
21//Cluster collections
22//
24//SCT Geometry
25//
27
28//Association tool
29//
30
32
33#include <ostream>
34#include <iomanip>
35#include <set>
36
37using namespace std;
38
40// Constructor
42
44(const std::string& t,const std::string& n,const IInterface* p)
45 : AthAlgTool(t,n,p)
46{
47 declareInterface<ITRT_SeededSpacePointFinder>(this);
48}
49
51// Destructor
53
55= default;
56
58// Initialisation
60
62{
64
65 // PRD-to-track association (optional)
66 ATH_CHECK( m_prdToTrackMap.initialize( !m_prdToTrackMap.key().empty()));
67 ATH_CHECK( m_fieldCondObjInputKey.initialize());
68 StatusCode sc = detStore()->retrieve(m_sctId, "SCT_ID");
69 if (sc.isFailure()){
70 msg(MSG::FATAL) << "Could not get SCT_ID helper !" << endmsg;
71 return StatusCode::FAILURE;
72 }
73
74 // Build framework
75 //
76
77 // Get output print level
78 //
79 if(msgLvl(MSG::DEBUG)){ dumpConditions(msg(MSG::DEBUG)); msg(MSG::DEBUG)<<endmsg; }
80
81 ATH_CHECK(m_spacepointsPixname.initialize());
82 ATH_CHECK(m_spacepointsSCTname.initialize());
84
85 return sc;
86}
87
89// Finalize
91
93{
94 StatusCode sc = AthAlgTool::finalize(); return sc;
95
96}
97
99// Initialize tool for new event
101
102std::unique_ptr<InDet::ITRT_SeededSpacePointFinder::IEventData>
104{
105 std::unique_ptr<InDet::TRT_SeededSpacePointFinder_ATL::EventData> event_data_p = std::make_unique<InDet::TRT_SeededSpacePointFinder_ATL::EventData>();
106 event_data_p->buildFrameWork(m_r_rmax, m_r_rstep, m_ptmin);
107 // @TODO remove m_r_Sorted and directly fill m_rf_Sorted ?
108
109 double irstep = 1./m_r_rstep;
110
111 std::vector< std::vector<const Trk::SpacePoint*> > r_Sorted;
112 r_Sorted.resize(event_data_p->m_r_size);
113
114 if(m_loadFull){
115 // Get pixel space points containers from store gate
116 //
118 if (spacepointsPix.isValid()) {
119 SpacePointContainer::const_iterator spc = spacepointsPix->begin ();
120 SpacePointContainer::const_iterator spce = spacepointsPix->end ();
121
122 for(; spc != spce; ++spc) {
123
125 SpacePointCollection::const_iterator spe = (*spc)->end ();
126 for(; sp != spe; ++sp) {
127
128 double r = (*sp)->r(); if(r<0. || r>=m_r_rmax) continue;
129 int ir = int(r*irstep);
130 const Trk::SpacePoint* sps = (*sp);
131 r_Sorted[ir].push_back(sps);
132 ++event_data_p->m_r_map[ir];
133 if(event_data_p->m_r_map[ir]==1) event_data_p->m_r_index[event_data_p->m_nr++] = ir;
134 ++event_data_p->m_ns;
135 }
136 }
137 }
138 }
139
140 SG::ReadHandle<Trk::PRDtoTrackMap> prd_to_track_map;
141 if (!m_prdToTrackMap.key().empty()) {
143 if (!prd_to_track_map.isValid()) {
144 ATH_MSG_ERROR("Failed to read PRD to track association map.");
145 }
146 }
147 // Get sct space points containers from store gate
148 //
150 if (spacepointsSCT.isValid()) {
151
152 SpacePointContainer::const_iterator spc = spacepointsSCT->begin();
153 SpacePointContainer::const_iterator spce = spacepointsSCT->end ();
154
155 double r_rmin = (!m_loadFull) ? m_r2min : m_r_rmin;
156 for(; spc != spce; ++spc) {
157
159 SpacePointCollection::const_iterator spe = (*spc)->end ();
160 for(; sp != spe; ++sp) {
161
162 if(prd_to_track_map.cptr()){
163 bool u1=false; bool u2=false;
164 const Trk::PrepRawData* p1=(*sp)->clusterList().first; u1=prd_to_track_map->isUsed(*p1);
165 const Trk::PrepRawData* p2=(*sp)->clusterList().second;u2=prd_to_track_map->isUsed(*p2);
166 if(u1 || u2){continue;}
167 }
168
169 double r = (*sp)->r(); if(r<r_rmin || r>=m_r_rmax) continue;
170 int ir = int(r*irstep);
171 const Trk::SpacePoint* sps = (*sp);
172 r_Sorted[ir].push_back(sps); ++event_data_p->m_r_map[ir];
173 if(event_data_p->m_r_map[ir]==1) event_data_p->m_r_index[event_data_p->m_nr++] = ir;
174 ++event_data_p->m_ns;
175 }
176 }
177 }
178
179 // Get sct overlap space points containers from store gate
180 //
182 if (spacepointsOverlap.isValid()) {
183 SpacePointOverlapCollection::const_iterator sp = spacepointsOverlap->begin();
184 SpacePointOverlapCollection::const_iterator spe = spacepointsOverlap->end ();
185
186 for (; sp!=spe; ++sp) {
187
188 if(prd_to_track_map.cptr()){
189 bool u1=false; bool u2=false;
190 const Trk::PrepRawData* p1=(*sp)->clusterList().first; u1=prd_to_track_map->isUsed(*p1);
191 const Trk::PrepRawData* p2=(*sp)->clusterList().second;u2=prd_to_track_map->isUsed(*p2);
192 if(u1 || u2){continue;}
193 }
194
195 double r = (*sp)->r(); if(r<0. || r>=m_r_rmax) continue;
196 int ir = int(r*irstep);
197 const Trk::SpacePoint* sps = (*sp);
198 r_Sorted[ir].push_back(sps); ++event_data_p->m_r_map[ir];
199 if(event_data_p->m_r_map[ir]==1) event_data_p->m_r_index[event_data_p->m_nr++] = ir;
200 ++event_data_p->m_ns;
201 }
202 }
203
204 fillLists(r_Sorted, *event_data_p); //Fill the R-phi sectors with the corresponding space points
205 return std::unique_ptr<InDet::ITRT_SeededSpacePointFinder::IEventData>(event_data_p.release());
206}
207
209// Initialize tool for new region
211
212std::unique_ptr<InDet::ITRT_SeededSpacePointFinder::IEventData> InDet::TRT_SeededSpacePointFinder_ATL::newRegion
213(const std::vector<IdentifierHash>& vPixel, const std::vector<IdentifierHash>& vSCT) const
214{
215 std::unique_ptr<InDet::TRT_SeededSpacePointFinder_ATL::EventData> event_data_p = std::make_unique<InDet::TRT_SeededSpacePointFinder_ATL::EventData>();
216 event_data_p->buildFrameWork(m_r_rmax, m_r_rstep, m_ptmin);
217
218 std::vector< std::vector<const Trk::SpacePoint*> > r_Sorted;
219 r_Sorted.resize(event_data_p->m_r_size);
220
221 double irstep = 1./m_r_rstep;
222
223 if(m_loadFull && !vPixel.empty()){
224 // Get pixel space points containers from store gate
225 //
227 if (spacepointsPix.isValid()) {
228 std::vector<IdentifierHash>::const_iterator l = vPixel.begin(), le = vPixel.end();
229
230 // Loop through all trigger collections
231 //
232 for(; l!=le; ++l) {
233
234 const SpacePointCollection *w = spacepointsPix->indexFindPtr(*l);
235 if(w==nullptr) continue;
238 for(; sp != spe; ++sp) {
239
240 double r = (*sp)->r(); if(r<0. || r>=m_r_rmax) continue;
241 int ir = int(r*irstep);
242 const Trk::SpacePoint* sps = (*sp);
243 r_Sorted[ir].push_back(sps); ++event_data_p->m_r_map[ir];
244 if(event_data_p->m_r_map[ir]==1) event_data_p->m_r_index[event_data_p->m_nr++] = ir;
245 ++event_data_p->m_ns;
246 }
247 }
248 }
249 }
250
251 // Get sct space points containers from store gate
252 //
253 if(!vSCT.empty()) {
254
256 if (spacepointsSCT.isValid()) {
257
258 SG::ReadHandle<Trk::PRDtoTrackMap> prd_to_track_map;
259 if (!m_prdToTrackMap.key().empty()) {
261 if (!prd_to_track_map.isValid()) {
262 ATH_MSG_ERROR("Failed to read PRD to track association map.");
263 }
264 }
265 std::vector<IdentifierHash>::const_iterator l = vSCT.begin(), le = vSCT.end();
266
267 // Loop through all trigger collections
268 //
269 double r_rmin = (!m_loadFull) ? m_r2min : m_r_rmin;
270 for(; l!=le; ++l) {
271
272 const SpacePointCollection *w = spacepointsSCT->indexFindPtr(*l);
273 if(w==nullptr) continue;
276 for(; sp != spe; ++sp) {
277
278 if(prd_to_track_map.cptr()){
279 bool u1=false; bool u2=false;
280 const Trk::PrepRawData* p1=(*sp)->clusterList().first; u1=prd_to_track_map->isUsed(*p1);
281 const Trk::PrepRawData* p2=(*sp)->clusterList().second;u2=prd_to_track_map->isUsed(*p2);
282 if(u1 || u2){continue;}
283 }
284
285 double r = (*sp)->r(); if(r<r_rmin || r>=m_r_rmax) continue;
286 int ir = int(r*irstep);
287 const Trk::SpacePoint* sps = (*sp);
288 r_Sorted[ir].push_back(sps); ++event_data_p->m_r_map[ir];
289 if(event_data_p->m_r_map[ir]==1) event_data_p->m_r_index[event_data_p->m_nr++] = ir;
290 ++event_data_p->m_ns;
291 }
292 }
293 }
294 }
295
296 fillLists(r_Sorted,*event_data_p); //Fill the R-phi sectors with the corresponding space points
297 return std::unique_ptr<InDet::ITRT_SeededSpacePointFinder::IEventData>(event_data_p.release());
298}
299
301// Methods to initialize different strategies of seeds production
302// with two space points with or without vertex constraint
304
305std::list<std::pair<const Trk::SpacePoint*, const Trk::SpacePoint*> >
307 const Trk::TrackParameters& tP,
308 ITRT_SeededSpacePointFinder::IEventData &virt_event_data) const
309{
311
312 const double pi2 = 2.*M_PI;
313
315 std::list<std::pair<const Trk::SpacePoint*,const Trk::SpacePoint*> > outputListBuffer;
316
318 double F = 0.;
319 double GPx=tP.position().x(); double GPy=tP.position().y();
320 F=atan2(GPy,GPx); if(F<0.) F+=pi2;
321 int f = int(F*event_data.m_sF);
322 if (f < 0)
323 f += event_data.m_fNmax;
324 else if (f > event_data.m_fNmax)
325 f -= event_data.m_fNmax;
326
327
328 production2Spb (ctx, tP,f, outputListBuffer,event_data); //Get a list of SP pairs.
329
330 if(msgLvl(MSG::DEBUG)) {
331 dumpEvent( msg(MSG::DEBUG), event_data);
332 dumpConditions( msg(MSG::DEBUG));
333 msg(MSG::DEBUG) << endmsg;
334 }
335
336 if(outputListBuffer.size()>10000.) outputListBuffer.clear();
337
338 return outputListBuffer;
339}
340
341
343// Dumps conditions information into the MsgStream
345
347{
348 int n = 42-m_fieldCondObjInputKey.key().size();
349 std::string s1; for(int i=0; i<n; ++i) s1.append(" "); s1.append("|");
350 n = 42-m_spacepointsSCTname.key().size();
351 std::string s3; for(int i=0; i<n; ++i) s3.append(" "); s3.append("|");
352 n = 42-m_spacepointsOverlapname.key().size();
353 std::string s4; for(int i=0; i<n; ++i) s4.append(" "); s4.append("|");
354
355 std::string fieldmode[9] ={"NoField" ,"ConstantField","SolenoidalField",
356 "ToroidalField" ,"Grid3DField" ,"RealisticField" ,
357 "UndefinedField","AthenaField" , "?????" };
358
359 int mode = m_fieldprop.magneticFieldMode();
360 if(mode<0 || mode>8 ) mode = 8;
361
362 n = 62-fieldmode[mode].size();
363 std::string s5; for(int i=0; i<n; ++i) s5.append(" "); s5.append("|");
364
365 out<<"|---------------------------------------------------------------------|"
366 <<std::endl;
367 out<<"| Key of magentic field condition Object | "<<m_fieldCondObjInputKey.key()<<s1
368 <<std::endl;
369 out<<"| SCT space points | "<<m_spacepointsSCTname.key()<<s3
370 <<std::endl;
371 out<<"| Overlap space points | "<<m_spacepointsOverlapname.key()<<s4
372 <<std::endl;
373 out<<"| Magnetic field mode | "<<fieldmode[mode]<<s5
374 <<std::endl;
375 out<<"| pTmin (mev) | "
376 <<std::setw(12)<<std::setprecision(5)<<m_ptmin
377 <<" |"<<std::endl;
378 out<<"| max radius SP | "
379 <<std::setw(12)<<std::setprecision(5)<<m_r_rmax
380 <<" |"<<std::endl;
381 out<<"| radius step | "
382 <<std::setw(12)<<std::setprecision(5)<<m_r_rstep
383 <<" |"<<std::endl;
384 out<<"| min radius second SP(3) | "
385 <<std::setw(12)<<std::setprecision(5)<<m_r2min
386 <<" |"<<std::endl;
387 out<<"| min radius first SP(3) | "
388 <<std::setw(12)<<std::setprecision(5)<<m_r12min
389 <<" |"<<std::endl;
390 out<<"| max radius first SP(3) | "
391 <<std::setw(12)<<std::setprecision(4)<<m_r1max
392 <<" |"<<std::endl;
393 out<<"| min seeds dZ/dR | "
394 <<std::setw(12)<<std::setprecision(5)<<m_dzdrmin
395 <<" |"<<std::endl;
396 out<<"| max seeds dZ/dR | "
397 <<std::setw(12)<<std::setprecision(5)<<m_dzdrmax
398 <<" |"<<std::endl;
399 out<<"| momentum chi2 cut | "
400 <<std::setw(12)<<std::setprecision(5)<<m_xiC
401 <<" |"<<std::endl;
402 out<<"| polar angle chi2 cut | "
403 <<std::setw(12)<<std::setprecision(5)<<m_xiTC
404 <<" |"<<std::endl;
405 out<<"| azimuthal angle chi2 cut | "
406 <<std::setw(12)<<std::setprecision(5)<<m_xiFC
407 <<" |"<<std::endl;
408 out<<"|---------------------------------------------------------------------|"
409 <<std::endl;
410 return out;
411}
412
414// Dumps event information into the MsgStream
416namespace {
417 class StreamState
418 {
419 public:
420 explicit StreamState(std::ostream& out)
421 : m_out(out), m_prec(out.precision())
422 {
423 }
424
425 ~StreamState()
426 {
427 m_out.precision(m_prec);
428 }
429
430 private:
431 std::ostream& m_out;
432 std::streamsize m_prec;
433 };
434}
435
437{
438 const double pi2 = 2.*M_PI;
439 out<<"|---------------------------------------------------------------------|"
440 <<"\n";
441 out<<"| m_ns | "
442 <<std::setw(12)<<event_data.m_ns
443 <<" |"<<"\n";
444 out<<"|---------------------------------------------------------------------|"
445 <<"\n";
446
447 if(msgLvl(MSG::DEBUG)) return out;
448
449 out<<"|-------------|--------|-------|-------|-------|-------|-------|";
450 out<<"-------|-------|-------|-------|-------|-------|"
451 <<"\n";
452
453 out<<"| Azimuthal | n | z[ 0] | z[ 1] | z[ 2] | z[ 3] | z[4] |";
454 out<<" z[ 5] | z[ 6] | z[ 7] | z[ 8] | z[ 9] | z[10] |"
455 <<"\n";
456 out<<"|-------------|--------|-------|-------|-------|-------|-------|";
457 out<<"-------|-------|-------|-------|-------|-------|"
458 <<"\n";
459
460 double sF1 = pi2/double(event_data.m_fNmax+1);
461
462 //StreamState restore_precision(out);
463 auto prec(out.precision());
464 for(int f=0; f<=event_data.m_fNmax; ++f) {
465 out<<"| "
466 <<std::setw(10)<<std::setprecision(4)<<sF1*double(f)<<" | "
467 <<std::setw(6)<<event_data.m_rf_map[f]<<" |";
468 out<<"\n";
469 }
470 out<<"|-------------|--------|-------|-------|-------|-------|-------|";
471 out<<"-------|-------|-------|-------|-------|-------|"
472 <<"\n";
473 out<<endmsg;
474 //coverity[STREAM_FORMAT_STATE:FALSE]
475 out.precision(prec);
476 return out;
477}
478
480// Dumps relevant information into the ostream
482
483MsgStream& InDet::TRT_SeededSpacePointFinder_ATL::dump( MsgStream& out ) const
484{
485 return dumpConditions(out);
486}
487
488std::ostream& InDet::TRT_SeededSpacePointFinder_ATL::dump( std::ostream& out ) const
489{
490 return out;
491}
492
494// Initiate frame work for seed generator
496
497void InDet::TRT_SeededSpacePointFinder_ATL::EventData::buildFrameWork(double r_rmax, double r_rstep, double ptmin)
498{
499
500 m_ns = m_nr = m_nrf = 0;
501
502 // Build radius sorted containers
503 //
504 m_r_size = int((r_rmax+.1)/r_rstep);
505 m_r_index = new int[m_r_size];
506 m_r_map = new int[m_r_size];
507 m_nr = 0; for(int i=0; i!=m_r_size; ++i) {m_r_index[i]=0; m_r_map[i]=0;}
508
509 // Build radius-azimuthal sorted containers
510 //
511 const double pi2 = 2.*M_PI ;
512 const int NFmax = 530 ;
513 const double sFmax = double(NFmax )/pi2;
514 m_sF = ptmin /60. ; if(m_sF >sFmax ) m_sF = sFmax ;
515 m_fNmax = int(pi2*m_sF); if(m_fNmax >=NFmax) m_fNmax = NFmax-1;
516 m_nrf = 0; for(int i=0; i!= 530; ++i) {m_rf_index [i]=0; m_rf_map [i]=0;}
517
518}
519
521// Initiate space points seed maker
523
524void InDet::TRT_SeededSpacePointFinder_ATL::fillLists(std::vector< std::vector<const Trk::SpacePoint*> > &r_Sorted,
526{
527 assert( static_cast<size_t>(event_data.m_r_size) == r_Sorted.size());
528 const double pi2 = 2.*M_PI;
529
530 for(int i=0; i!= event_data.m_r_size; ++i) {
531 if(!event_data.m_r_map[i]) continue;
532 for(const Trk::SpacePoint *space_point : r_Sorted[i]) {
533
534 // Azimuthal angle sort
535 //
536 double F = space_point->phi(); if(F<0.) F+=pi2;
537 int f = int(F*event_data.m_sF);
538 if (f < 0)
539 f += event_data.m_fNmax;
540 else if (f > event_data.m_fNmax)
541 f -= event_data.m_fNmax;
542 int isBRL = 1000; int isLYR = 1000; int DD = 1000;
543
544 geoInfo(space_point,isBRL,isLYR);
545
546 // Use 4 lower bits (Mask == ((2^4 -1) == 15)) for isLYR
547 // the upper 28 bits for isBRL (including sign)
548 DD = ((isBRL+3) << 4) + (isLYR & 15);
549
550 event_data.m_rf_Sorted[f].emplace_back(space_point,DD);
551 if(!event_data.m_rf_map[f]++) event_data.m_rf_index[event_data.m_nrf++] = f;
552
553 }
554 event_data.m_r_map[i] = 0;
555 }
556
557 event_data.m_nr = 0;
558}
559
561// Erase space point information
563
565{
566
567 for(int i=0; i!=m_nrf; ++i) {
568 int n = m_rf_index[i]; m_rf_map[n] = 0;
569 m_rf_Sorted[n].erase(m_rf_Sorted[n].begin(),m_rf_Sorted[n].end());
570 }
571
572 m_ns = 0;
573 m_nr = 0;
574 m_nrf = 0;
575}
576
577// // // // // // // // // // // // // // // // // // // // // // // // // //
578
579// Monotonic function of the angle to map the comparison to replace atan2
580// Computation is not in the inner loop, so trigonometric functions are OK
581double
583 while (angle < 0) {
584 angle += 2*M_PI;
585 }
586 while (angle > 2*M_PI) {
587 angle -= 2*M_PI;
588 }
589 double rotations = angle/(2*M_PI);
590 double rquadrant = rotations*4.0;
591 long quadrant = (long)rquadrant & 3;
592 double twist;
593 if ((quadrant & 1) != 0) {
594 twist = cos(angle);
595 }
596 else {
597 twist = sin(angle);
598 }
599 twist *= twist;
600 quadrant -= ((quadrant & 2) << 1);
601 return quadrant + twist;
602}
603
604// Since the theta and phi cuts in cutTP are essentially
605// checks for the angle to be within a specified region,
606// only the upper and the lower boundaries have to calculated,
607// once again, not in the inner loop but just once
608// The logic is:
609// {lower <= angle <= upper_} necessary and sufficient for
610// {rollrating(lower) <= rollrating(angle) <= rollrating(upper)}
611void
612bracket_angle(double angle, double delta,
613 double *min, double *max) {
614 double amin = rollrating(angle - delta);
615 double amax = rollrating(angle + delta);
616 if (delta >= M_PI) {
617 amin = 0.0;
618 amax = 4.0;
619 }
620 *min = amin;
621 *max = amax;
622}
623
624
625// rotrating(sin(angle), cos(angle)) == rollrating(angle)
626// Called many times, for each pair still in consideration
627// Performance critical, so no SQRTs or transcendentals here
628inline double
629rotrating(double y, double x) {
630 long asign_x = (long)(x < 0.0);
631 long asign_y = (long)(y < 0.0);
632 long quadrant = -(asign_y << 1) + (asign_y ^ asign_x);
633 double x2 = x*x;
634 double y2 = y*y;
635 double denominator = x2 + y2;
636 double numerator = ((quadrant & 1) != 0) ? x2 : y2;
637 return (double)quadrant + numerator/denominator;
638}
639
640void
642 const Trk::TrackParameters& tP,
643 int phi,
644 std::list<std::pair<const Trk::SpacePoint*,const Trk::SpacePoint*> > &outputListBuffer,
646{
647 uint64_t spcount = 0;
648 // // // // // // <Fill the invar_bypass // // // // // // //
649
650 //const Trk::MeasuredAtaStraightLine &ntP =
651 //dynamic_cast<const Trk::MeasuredAtaStraightLine&>(tP);
652 const AmgVector(5)& pTS=tP.parameters();
653 const AmgSymMatrix(5)* vCM = tP.covariance();
654
655 double sPhi = (*vCM)(2,2) ; //Sigma on TRT segment azimuthal angle
656 double sTheta = (*vCM)(3,3); //Sigma on TRT segment polar angle
657 double sp = (*vCM)(4,4) ; //Sigma on TRT segment inverse momentum estimate
658
659 double ipdelta = sqrt(m_xiC*sp);
660
661 invar_bypass_struct tmp_invar_bypass{};
662 tmp_invar_bypass.invp_min = pTS[4] - ipdelta;
663 tmp_invar_bypass.invp_max = pTS[4] + ipdelta;
664
665 tmp_invar_bypass.invp_min2 = tmp_invar_bypass.invp_min*tmp_invar_bypass.invp_min;
666 tmp_invar_bypass.invp_max2 = tmp_invar_bypass.invp_max*tmp_invar_bypass.invp_max;
667
668 double theta_center = pTS[3];
669 double theta_delta = sqrt(m_xiTC*sTheta);
670
671 double phi_center = pTS[2];
672 double phi_delta = sqrt(m_xiFC*sPhi);
673
674 bracket_angle(theta_center, theta_delta,
675 &(tmp_invar_bypass.min_theta), &(tmp_invar_bypass.max_theta));
676 bracket_angle(phi_center, phi_delta,
677 &(tmp_invar_bypass.min_phi), &(tmp_invar_bypass.max_phi));
678
679 // // // // // // Fill the invar_bypass> // // // // // // //
680
682 double x0=tP.position().x() ;
683 double y0=tP.position().y() ;
684 double z0=tP.position().z() ;
685 double H[3]; double gP[3] = {x0,y0,z0};
686
687 // Get field cache object
689 const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
690 if (fieldCondObj == nullptr) {
691 ATH_MSG_ERROR("TRT_SeededSpacePointFinder_ATL: Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCondObjInputKey.key());
692 return;
693 }
694 MagField::AtlasFieldCache fieldCache;
695 fieldCondObj->getInitializedCache (fieldCache);
696 fieldCache.getField (gP, H);
697
698 //need conversion kilotesla -> kilogauss - Previously used getMagneticFiledKiloGauss, whereas new function returns value in kiloTesla...
699 H[0] *= 10000;
700 H[1] *= 10000;
701 H[2] *= 10000;
702
703 std::list<std::pair<const Trk::SpacePoint*,int> >::iterator r0,r0e,r,re, rb;
704 const Trk::SpacePoint* SpToPair = nullptr;
705
706
708 //
709 int fmin=phi; int fmax=phi;
710 if(m_search){fmin = phi-1; fmax = phi+1;}
711 for(int f=fmin; f<=fmax; ++f) {
712 int j=0; f<0 ? j=f+event_data.m_fNmax+1 : f>event_data.m_fNmax ? j=f-event_data.m_fNmax-1 : j=f;
713 if(!event_data.m_rf_map[j]){
714 continue;
715 }
716 r0 = event_data.m_rf_Sorted[j].begin();
717 r0e = event_data.m_rf_Sorted[j].end();
718
720 for(; r0!=r0e; ++r0){
721 if((((*r0).first)->r() > m_r1max) ||
722 (((*r0).first)->r() < m_r2min)) {
723 continue; //Fill only the SCT SPs
724 }
725 event_data.m_newRfi_Sorted.push_back(*r0);
726 }
727 }
728
729 if(event_data.m_newRfi_Sorted.size()>5000 && event_data.m_newRfi_Sorted.size()<=10000) {
730 event_data.m_newRfi_Sorted.erase(event_data.m_newRfi_Sorted.begin(),event_data.m_newRfi_Sorted.end());
731 int fmin=phi; int fmax=phi;
732 for(int f=fmin; f<=fmax; ++f) {
733 int j=0; f<0 ? j=f+event_data.m_fNmax+1 : f>event_data.m_fNmax ? j=f-event_data.m_fNmax-1 : j=f;
734 if(!event_data.m_rf_map[j]){
735 continue;
736 }
737 r0 = event_data.m_rf_Sorted[j].begin();
738 r0e = event_data.m_rf_Sorted[j].end();
739
741 for(; r0!=r0e; ++r0){
742 if((((*r0).first)->r()>m_r1max) || (((*r0).first)->r()<m_r2min)) {
743 continue; //Fill only the SCT SPs
744 }
745 event_data.m_newRfi_Sorted.push_back(*r0);
746 }
747 }
748 }
749 if(event_data.m_newRfi_Sorted.size()>10000) {
750 event_data.m_newRfi_Sorted.erase(event_data.m_newRfi_Sorted.begin(),event_data.m_newRfi_Sorted.end());
751 return;
752 }
753
754 event_data.m_newRfi_Sorted.sort(MyNewDataSortPredicate());
755
756 spcount = event_data.m_newRfi_Sorted.size();
757
758 r = event_data.m_newRfi_Sorted.begin();
759 re = event_data.m_newRfi_Sorted.end();
760
761 std::vector<bypass_struct> tmp_prod_bypass;
762 std::vector<const Trk::SpacePoint *> vrp;
763 std::vector<double> rk;
764 std::vector<long> geo_info;
765 std::vector<double> zSP;
766 tmp_prod_bypass.reserve(spcount);
767 vrp.reserve(spcount);
768 rk.reserve(spcount);
769 geo_info.reserve(spcount);
770 zSP.reserve(spcount);
771
772 // // // // // // <Fill m_prod_bypass and the local array // // // //
773 for (; r != re; ++r) {
774 const Trk::SpacePoint *vrpi = (*r).first;
775
776 geo_info.push_back((*r).second);
777 vrp.push_back(vrpi);
778 rk.push_back(vrpi->r());
779
780 double X = vrpi->globalPosition().x() - x0;
781 double Y = vrpi->globalPosition().y() - y0;
782 double zSPi = vrpi->globalPosition().z();
783 zSP.push_back(zSPi);
784 double Z = zSPi - z0;
785
786 double RR = X*X + Y*Y;
787 double R = sqrt(RR);
788 double invR = 1.0/R;
789
790 double a = X*invR;
791 double b = Y*invR;
792
793 tmp_prod_bypass.emplace_back();
794 tmp_prod_bypass.back().X = X;
795 tmp_prod_bypass.back().Y = Y;
796 tmp_prod_bypass.back().Z = Z;
797
798 tmp_prod_bypass.back().R = R;
799 tmp_prod_bypass.back().invR = invR;
800
801 tmp_prod_bypass.back().a = a;
802 tmp_prod_bypass.back().b = b;
803 }
804
805 // // // // // // Fill m_prod_bypass and the local array> // // // //
806
808
809 if (m_doCosmics) { // no need to check this every time in the loop
810 for (long i = 0; i < (long)spcount; i++) {
811 SpToPair = nullptr;
812 const Trk::SpacePoint *up = vrp[i];
813 for (long j = i + 1; j < (long)spcount; j++) {
814 const Trk::SpacePoint *bp = vrp[j];
815 SpToPair = bp;
816 outputListBuffer.emplace_back(up, SpToPair);
817 }
818 if(!SpToPair) {
819 outputListBuffer.emplace_back(up, up);
820 }
821 }
822 }
823 else { // (!m_doCosmics)
824 for (long i = 0; i < (long)spcount; i++) {
825 SpToPair = nullptr;
826 const Trk::SpacePoint *up = vrp[i];
827 double R = rk[i];
828 if(R<m_r12min) {
829 continue;
830 }
831 double Z = zSP[i];
832 long geoi = geo_info[i];
833 int isBU = (geoi >> 4)-3;
834 int eleU = geoi & 15;
835
836 for (long j = i + 1; j < (long)spcount; j++) {
837 const Trk::SpacePoint *bp = vrp[j];
838 double Zb = zSP[j];
839 double Rb = rk[j];
840 long geoj = geo_info[j];
841 int isBB = (geoj >> 4)-3;
842 int eleB = geoj & 15;
843 // // // // // // // // // // // // // // // // // // // // // //
844
845 // Equivalent to {
846 // if ((isBU == 0) && (isBB != isBU)) continue;
847 // if((isBU == isBB) && (eleU <= eleB)) continue;
848 // }
849 // Rather cryptic but 2 to 3 times faster
850 // than the 4 branches above...
851
852 int Bd = (isBU - isBB) | (isBB - isBU);
853 int Ed = (eleB - eleU);
854 int BUzero = (isBU | -isBU);
855 if (((BUzero | ~Bd) & (Bd | Ed) & (((unsigned)(-1) >> 1) + 1))
856 == 0) {
857 continue;
858 }
859
860 // // // // // // // // // // // // // // // // // // // // // //
861 double dR = R - Rb;
862 double dZ = Z - Zb;
863 double dz_min = m_dzdrmin*dR;
864 double dz_max = m_dzdrmax*dR;
865 if (dZ < dz_min || dZ > dz_max) {
866 continue;//Should be within the +-2.5 pseudorapidity range
867 }
868 if(fieldCache.solenoidOn()) {
869 if(!cutTPb(tmp_invar_bypass, tmp_prod_bypass,i, j, H[2])) {
870 continue;
871 }
872 }
873 SpToPair = bp;
874 outputListBuffer.emplace_back(up, SpToPair);
875 }
876 if(!SpToPair) {
877 outputListBuffer.emplace_back(up, up);
878 }
879 }
880 }
881
882 event_data.m_newRfi_Sorted.erase(event_data.m_newRfi_Sorted.begin(),event_data.m_newRfi_Sorted.end());
883}
884
885// comment out to enable angle discontinuity correction
886// so that e.g. angles PI-epsilon and -Pi+epsilon are treated
887// as being 2*epsilon apart as they should, instead of 2*Pi-2*epsilon
888// as they would w/o this correction
889//#define ANGLE_DISCO_COMPAT
890
891bool
893 const std::vector<bypass_struct> &tmp_prod_bypass,
894 long bSP1, long bSP2, double H) const
895{
896
897 double inv_r2 = tmp_prod_bypass[bSP2].invR;
898 double inv_r1 = tmp_prod_bypass[bSP1].invR; // == u1 in original cutTP
899 double r1 = tmp_prod_bypass[bSP1].R;
900
901 double inv_rr2 = inv_r2*inv_r2;
902 double x2 = tmp_prod_bypass[bSP2].X;
903 double y2 = tmp_prod_bypass[bSP2].Y;
904 double a1 = tmp_prod_bypass[bSP1].a;
905 double b1 = tmp_prod_bypass[bSP1].b;
906
907 double u2 = (a1*x2 + b1*y2)*inv_rr2;
908 double v2 = (a1*y2 - b1*x2)*inv_rr2;
909
910 double A = v2/(u2 - inv_r1);
911 double B = 2.0*(v2 - A*u2);
912 double CC = B*B/(1.0 + A*A);
913 double rcrc = CC*r1*r1;
914 double z1 = tmp_prod_bypass[bSP1].Z;
915 double T = -z1/(r1*(1.0 + 0.04*rcrc));
916
917 if(H==0.) return false;
918
919 double invpSignature = B*H;
920
921 double invP2 = CC/(0.03*0.03*H*H*(1.0 + T*T));
922
923 if (invpSignature >= 0 && invP2*0.9*0.9*m_ptmin*m_ptmin > 1.0) {
924 return false;
925 }
926
927 double invp_min = tmp_invar_bypass.invp_min;
928 double invp_max = tmp_invar_bypass.invp_max;
929
930 double invp_min2 = tmp_invar_bypass.invp_min2;
931 double invp_max2 = tmp_invar_bypass.invp_max2;
932
933 if (invp_min >= 0) {
934 if (invpSignature < 0 || invP2 < invp_min2) {
935 return false;
936 }
937 }
938 else {
939 if (invpSignature < 0 && invP2 > invp_min2) {
940 return false;
941 }
942 }
943 if (invp_max >= 0) {
944 if (invpSignature >= 0 && invP2 > invp_max2) {
945 return false;
946 }
947 }
948 else {
949 if (invpSignature >= 0 || invP2 < invp_max2) {
950 return false;
951 }
952 }
953
954 //Estimate the seed polar angle. Make a chi2 cut based on that suggested by the TRT segment
955
956 double theta_rating = rotrating(1.0, T);
957 double tmin = tmp_invar_bypass.min_theta;
958 double tmax = tmp_invar_bypass.max_theta;
959
960 if (tmin > tmax) {
961#ifndef ANGLE_DISCO_COMPAT
962 // correct math but incompatible with old version
963 if (theta_rating >= 0) {
964 tmax += 4.0;
965 }
966 else {
967 tmin -= 4.0;
968 }
969#else
970 // compatibility mode
971 if (tmin + tmax <= 0) {
972 // center in "+" (YES, "+") range; any negative theta_rating => false
973 tmax = 2.0; // forcing range into all positive
974 }
975 else {
976 // center in "-" (YES, "-") range; any positive theta_rating => false
977 tmin = -2.0; // forcing range into all negative
978 }
979#endif
980 }
981
982 if (theta_rating < tmin || theta_rating > tmax) {
983 return false;
984 }
985
986 double phi_rating = rotrating(-(b1 + a1*A), -(a1 - b1*A));
987 double pmin = tmp_invar_bypass.min_phi;
988 double pmax = tmp_invar_bypass.max_phi;
989
990 if (pmin > pmax) {
991#ifndef ANGLE_DISCO_COMPAT
992 // correct math but incompatible with old version
993 if (phi_rating >= 0) {
994 pmax += 4.0;
995 }
996 else {
997 pmin -= 4.0;
998 }
999#else
1000 // compatibility mode
1001 if (pmin + pmax <= 0) {
1002 // center in "+" (YES, "+") range; any negative phi_rating => false
1003 pmax = 2.0; // forcing range into all positive
1004 }
1005 else {
1006 // center in "-" (YES, "-") range; any positive phi_rating => false
1007 pmin = -2.0; // forcing range into all negative
1008 }
1009#endif
1010 }
1011
1012 return phi_rating >= pmin && phi_rating <= pmax;
1013}
1014
1015// // // // // // // // // // // // // // // // // // // // // // // // // //
1016
1017
1019// Check whether the SP belongs to a barrel or an endcap element
1021
1022void
1024{
1025 const Trk::PrepRawData* p1;
1026 const InDet::SCT_Cluster* c1;
1027 Identifier id;
1028
1029 p1 = SP->clusterList().first;
1030 if(p1){
1031 c1=dynamic_cast<const InDet::SCT_Cluster*>(p1);
1032 if(c1){
1033 id=c1->detectorElement()->identify();
1034 isB = m_sctId->barrel_ec(id);
1035 ld = m_sctId->layer_disk(id);
1036 }
1037 }
1038
1039}
1040
1042// MagneticFieldProperties production
1044
const std::regex re(r_e)
#define M_PI
Scalar phi() const
phi method
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define AmgSymMatrix(dim)
#define AmgVector(rows)
static Double_t sp
static Double_t a
static Double_t sc
#define F(x, y, z)
Definition MD5.cxx:112
#define H(x, y, z)
Definition MD5.cxx:114
This is an Identifier helper class for the SCT subdetector.
Handle class for reading from StoreGate.
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
double rotrating(double y, double x)
void bracket_angle(double angle, double delta, double *min, double *max)
double rollrating(double angle)
#define y
#define x
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
const ServiceHandle< StoreGateSvc > & detStore() const
bool msgLvl(const MSG::Level lvl) const
MsgStream & msg() const
void getInitializedCache(MagField::AtlasFieldCache &cache) const
get B field cache for evaluation as a function of 2-d or 3-d position.
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
Sorting function according to space point radial position.
std::list< std::pair< const Trk::SpacePoint *, int > > m_newRfi_Sorted
std::list< std::pair< const Trk::SpacePoint *, int > > m_rf_Sorted[530]
void buildFrameWork(double r_rmax, double r_rstep, double ptmin)
std::unique_ptr< InDet::ITRT_SeededSpacePointFinder::IEventData > newEvent() const
Method to initialize tool for new event.
static constexpr double m_dzdrmax
Min R-z direction cut.
DoubleProperty m_ptmin
Seed selection criteria.
SG::ReadHandleKey< SpacePointOverlapCollection > m_spacepointsOverlapname
static constexpr double m_r_rmax
Minimum SCT radius to be searched.
static constexpr double m_r1max
Step size for space point storage.
std::list< std::pair< const Trk::SpacePoint *, const Trk::SpacePoint * > > find2Sp(const EventContext &ctx, const Trk::TrackParameters &, ITRT_SeededSpacePointFinder::IEventData &event_data) const
Main method of seed production.
static constexpr double m_dzdrmin
Min radius to search for SP pairs.
const SCT_ID * m_sctId
Magnetic field properties.
SG::ReadHandleKey< SpacePointContainer > m_spacepointsPixname
Space points containers.
TRT_SeededSpacePointFinder_ATL(const std::string &, const std::string &, const IInterface *)
Standard tool methods.
SG::ReadHandleKey< Trk::PRDtoTrackMap > m_prdToTrackMap
static constexpr double m_r2min
Min radius of last SCT layer.
void magneticFieldInit()
Get magnetic field properties.
SG::ReadHandleKey< SpacePointContainer > m_spacepointsSCTname
static constexpr double m_r12min
Max radius of last SCT layer.
void geoInfo(const Trk::SpacePoint *, int &, int &) const
Obtain geo model info for a specific space point.
MsgStream & dumpConditions(MsgStream &out) const
Protected methods.
void fillLists(std::vector< std::vector< const Trk::SpacePoint * > > &r_Sorted, InDet::TRT_SeededSpacePointFinder_ATL::EventData &event_data) const
Fill the space point container lists at beginning of each event.
void production2Spb(const EventContext &ctx, const Trk::TrackParameters &, int, std::list< std::pair< const Trk::SpacePoint *, const Trk::SpacePoint * > > &outputListBuffer, InDet::TRT_SeededSpacePointFinder_ATL::EventData &event_data) const
Form possible space point combinations within allowed radial and pseudorapidity ranges.
MsgStream & dumpEvent(MsgStream &out, InDet::TRT_SeededSpacePointFinder_ATL::EventData &event_data) const
bool cutTPb(const invar_bypass_struct &invar_bypass, const std::vector< bypass_struct > &prod_bypass, long, long, double) const
Cut on chi2 based on TRT segment qOverP, theta and phi track parameters.
static constexpr double m_r_rstep
Maximum STC radius to be searched.
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCondObjInputKey
std::unique_ptr< InDet::ITRT_SeededSpacePointFinder::IEventData > newRegion(const std::vector< IdentifierHash > &, const std::vector< IdentifierHash > &) const
StringProperty m_fieldmode
Protected data and methods.
MsgStream & dump(MsgStream &out) const
Print internal tool parameters and status.
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h).
bool solenoidOn() const
status of the magnets
void getField(const double *ATH_RESTRICT xyz, double *ATH_RESTRICT bxyz, double *ATH_RESTRICT deriv=nullptr)
get B field value at given position xyz[3] is in mm, bxyz[3] is in kT if deriv[9] is given,...
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
static EventData & getPrivateEventData(InDet::ITRT_SeededSpacePointFinder::IEventData &virt_event_data)
magnetic field properties to steer the behavior of the extrapolation
const Amg::Vector3D & position() const
Access method for the position.
double r() const
returns the r value of the SpacePoint's position (in cylindrical coordinates).
const std::pair< const PrepRawData *, const PrepRawData * > & clusterList() const
return the pair of cluster pointers by reference
virtual const Amg::Vector3D & globalPosition() const override final
Interface method to get the global Position.
int ir
counter of the current depth
Definition fastadd.cxx:49
int r
Definition globals.cxx:22
@ FastField
call the fast field access method of the FieldSvc
@ NoField
Field is set to 0., 0., 0.,.
@ FullField
Field is set to be realistic, but within a given Volume.
ParametersBase< TrackParametersDim, Charged > TrackParameters
STL namespace.
hold the test vectors and ease the comparison