ATLAS Offline Software
Loading...
Searching...
No Matches
FPGATrackSimLLPDoubletHoughTransformTool.cxx
Go to the documentation of this file.
1// Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2
3#include "TH2.h"
5
6// simple 2D vector with basic arithmetics
7typedef double fp_t; // floating point type alias, can change it to float from double
8
9typedef std::array<fp_t, 2> pvec;
10pvec operator+(const pvec& a, const pvec& b);
11pvec operator-(const pvec& a, const pvec& b);
12pvec operator*(const pvec& a, double scale);
13
14
15pvec operator+(const pvec& a, const pvec& b) {
16 return { {a[0]+b[0], a[1]+b[1]} };
17}
18pvec operator-(const pvec& a, const pvec& b) {
19 return { {a[0]-b[0], a[1]-b[1]} };
20
21}
22pvec operator*(const pvec& a, double scale) {
23 return { {a[0]*scale, a[1]*scale} };
24}
25
26double length(const pvec& v) {
27 return std::hypot(v[0], v[1]);
28}
29
30pvec rotate90( const pvec& v) {
31 return { -v[1], v[0]};
32}
33
34double crossProduct( const pvec& a, const pvec& b ) {
35 return a[0]*b[1] - a[1]*b[0];
36}
37
39 if (m_imageSize_y %2 == 1) {
40 ATH_MSG_ERROR("Can not have odd number " << m_imageSize_y << " of bins in q/pT - will result in division by 0");
41 return StatusCode::FAILURE;
42 }
45
46 return StatusCode::SUCCESS;
47 }
48
50 ATH_MSG_INFO("Number of events procesed by the FPGATrackSimLLPDoubletHoughTransformTool " << m_eventsProcessed << " roads " << m_roadsGenerated);
51 return StatusCode::SUCCESS;
52}
53
54StatusCode FPGATrackSimLLPDoubletHoughTransformTool::getRoads(const std::vector<std::shared_ptr<const FPGATrackSimHit>> & hits, std::vector<std::shared_ptr<const FPGATrackSimRoad>> & roads) {
55 roads.clear();
56 m_roads.clear();
58 Image image(m_imageSize_x, m_imageSize_y); // not quite optimal to allocate this memory in evey event, but following nominal HT
59 for (unsigned ihit1 = 0; ihit1 < hits.size(); ihit1++) {
60 std::shared_ptr<const FPGATrackSimHit> hit1 = hits[ihit1];
61 for (unsigned ihit2 = ihit1+1; ihit2 < hits.size(); ihit2++) {
62 std::shared_ptr<const FPGATrackSimHit> hit2 = hits[ihit2];
63 ATH_MSG_DEBUG("Hits pair R: " << hit1->getR() << " " << hit2->getR());
64 //TODO: replace with qualification by layer IDs
65 const double radiusDifference = hit2->getR() - hit1->getR();
66
67 if ( not (m_acceptedDistanceBetweenLayersMin < radiusDifference && radiusDifference < m_acceptedDistanceBetweenLayersMax) )
68 continue;
69 if ( hit1->getLayer() == hit2->getLayer() )
70 continue;
71 ATH_CHECK(fillImage( hit1, hit2, image ));
72 }
73 }
74 if ( m_event < 20 )
75 drawImage(image);
76
77 for (unsigned y = 0; y < m_imageSize_y; y++) {
78 for (unsigned x = 0; x < m_imageSize_x; x++) {
79 if (passThreshold(image, x, y) && isLocalMaxima( image, x, y ) ) {
80 ATH_MSG_DEBUG("Creating road with threshold " << image(x,y).first << " hits " << image(x,y).second.size()
81 << " at x: " << x << " d0 " << xtod0(x) << " y: "<< y << " q/pt " << ytoqoverpt(y));
83 m_roads.push_back(createRoad(image(x, y).second, x, y));
84 }
85 }
86 }
87 roads.reserve(m_roads.size());
88 for (FPGATrackSimRoad & r : m_roads) roads.emplace_back(std::make_shared<const FPGATrackSimRoad>(r));
89 m_event++;
90 return StatusCode::SUCCESS;
91}
92
93
94StatusCode FPGATrackSimLLPDoubletHoughTransformTool::fillImage(std::shared_ptr<const FPGATrackSimHit> &hit1, std::shared_ptr<const FPGATrackSimHit> &hit2, Image& image) const {
95 const pvec p1 {{hit1->getX(), hit1->getY()}};
96 const pvec p2 {{hit2->getX(), hit2->getY()}};
97 const pvec halfDiff = (p2 - p1)*0.5;
98 const fp_t halfLen = length(halfDiff);
99
100 int xbefore = -1;
101
102 for ( unsigned y = 0; y < m_imageSize_y; y++ ) {
103 const fp_t qoverpt = (y * m_step_y) + m_step_y*0.5 - m_qOverPt_range; // use middle f the bin
104 const fp_t radius = 1.0/(0.6*qoverpt); // magic transform constants
105 const fp_t scale = std::copysign( std::sqrt( std::pow(radius/halfLen, 2) - 1), radius );
106 const pvec rprime = rotate90(halfDiff) * scale;
107 const pvec center = p1 + halfDiff + rprime;
108 const fp_t d0 = (std::signbit(radius) ? -1.0 : 1.0)*(length(center) - abs(radius));
109
110 // find the bin x position in the image
111 int x = (d0 + m_d0_range) / m_step_x;
112
113 if ( 0 <= x && x < (int)m_imageSize_x) {
114 if (xbefore == -1) xbefore = x;
115 if ( m_continuous ) { // fill the bins along x starintg from the last one filled
116 const int xmin = (xbefore < x)? xbefore: x;
117 const int xmax = (xbefore < x)? x: xbefore;
118 for ( int xinterpolated = xmin; xinterpolated <= xmax; ++xinterpolated) {
119 image(xinterpolated, y).first++;
120 image(xinterpolated, y).second.insert( hit1 );
121 image(xinterpolated, y).second.insert( hit2 );
122 }
123 } else {
124 image(x, y).first++;
125 image(x, y).second.insert( hit1 );
126 image(x, y).second.insert( hit2 );
127 }
128 xbefore = x;
129 }
130 }
131 return StatusCode::SUCCESS;
132}
133
134FPGATrackSimRoad FPGATrackSimLLPDoubletHoughTransformTool::createRoad(const std::unordered_set<std::shared_ptr<const FPGATrackSimHit>> & hits, unsigned /*x*/, unsigned /*y*/) const {
135 // Get the road hits
136 std::vector<std::shared_ptr<const FPGATrackSimHit>> road_hits;
137 layer_bitmask_t hitLayers = 0;
138 for (const auto & hit : hits)
139 {
140 road_hits.push_back(hit);
141 hitLayers |= 1 << hit->getLayer();
142 }
143
144 auto sorted_hits = ::sortByLayer(road_hits);
145 sorted_hits.resize(8); // If no hits in last layer, return from sortByLayer will be too short
146
148 r.setHitLayers(hitLayers);
149 r.setHits(std::move(sorted_hits));
150 return r;
151}
152
153
155 const int count = image(x,y).first;
156 const float d0 = xtod0(x);
157 if ( std::abs(d0) < 50.0 && count >= m_threshold50 ) return true;
158 if ( std::abs(d0) >= 50.0 && count >= m_threshold ) return true;
159
160 return false;
161}
162
164 const auto centerValue = image(x,y).first;
165 for ( int xaround = std::min(x-1, 0); xaround <= std::max((int)m_imageSize_x-1, x+1); xaround++ ) {
166 for ( int yaround = std::min(y-1, 0); yaround <= std::max((int)m_imageSize_y-1, y+1); yaround++ ) {
167 if ( image(xaround,yaround).first > centerValue )
168 return false;
169 }
170 }
171 return true;
172}
173
175
176 TH2I h(("event"+std::to_string( m_event )).c_str(), "LLP Doublet Hough space;d_{0}[mm];q/pT [e/GeV]",
179
180 for (unsigned x = 0; x < m_imageSize_x; x++)
181 for (unsigned y = 0; y < m_imageSize_y; y++)
182 h.SetBinContent(x+1, y+1, image(x, y).first); // +1 since root bins are 1-indexed
183
184 h.SaveAs((name()+"_event_"+std::to_string( m_event )+".root").c_str(), "");
185}
186
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
std::vector< std::vector< std::shared_ptr< const FPGATrackSimHit > > > sortByLayer(Container const &hits)
pvec operator+(const pvec &a, const pvec &b)
pvec operator-(const pvec &a, const pvec &b)
pvec rotate90(const pvec &v)
std::array< fp_t, 2 > pvec
double length(const pvec &v)
pvec operator*(const pvec &a, double scale)
double crossProduct(const pvec &a, const pvec &b)
uint32_t layer_bitmask_t
static Double_t a
#define y
#define x
Header file for AthHistogramAlgorithm.
bool passThreshold(Image const &image, int x, int y) const
bool isLocalMaxima(Image const &image, int x, int y) const
virtual StatusCode getRoads(const std::vector< std::shared_ptr< const FPGATrackSimHit > > &hits, std::vector< std::shared_ptr< const FPGATrackSimRoad > > &roads) override
FPGATrackSimRoad createRoad(const std::unordered_set< std::shared_ptr< const FPGATrackSimHit > > &hits, unsigned x, unsigned y) const
StatusCode fillImage(std::shared_ptr< const FPGATrackSimHit > &hit1, std::shared_ptr< const FPGATrackSimHit > &hit2, Image &image) const
vector2D< std::pair< int, std::unordered_set< std::shared_ptr< const FPGATrackSimHit > > > > Image
int r
Definition globals.cxx:22
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:146
double xmax
Definition listroot.cxx:61
double xmin
Definition listroot.cxx:60