ATLAS Offline Software
Loading...
Searching...
No Matches
MuonHoughTransformer_CurvedAtACylinder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
6
8#include "CxxUtils/sincos.h"
9#include "GaudiKernel/MsgStream.h"
10
12 double detectorsize_angle, double threshold_histo,
13 int number_of_sectors) :
14 MuonHoughTransformer("MuonHoughTransformer_CurvedAtACylinder", nbins, nbins_angle, detectorsize, detectorsize_angle, threshold_histo, number_of_sectors) {
15 m_add_weight_radius = false;
17 m_add_weight_angle = false;
18
19 // fill array with scanned curvatures
20
21 m_invcurvature.reset(new double[m_nbins / 2]);
22 m_weightcurvature.reset(new double[m_nbins / 2]);
23
24 for (int i = 0; i < m_nbins / 2; i++) {
25 double x0 = -i + 24; // 24 ... -55
26 if (x0 > 15.) x0 = 15 + (x0 - 15) * 0.5; // 19.5,19,18.5, .., 15.5,15,14,13,.. 2,1,0,-1...-55 // 80 bins
27
28 double curvature = -3. * 3500. * 20.25 / (x0 - 19.75); // >0
29 m_invcurvature[i] = 1. / curvature;
30 if (i <= 10) {
31 m_weightcurvature[i] = 1.;
32 } else if (i <= 20) {
33 m_weightcurvature[i] = 1 - 0.05 * (i - 10);
34 } else {
35 m_weightcurvature[i] = 0.5;
36 }
37 }
38}
39
40
41void MuonHoughTransformer_CurvedAtACylinder::fillHit(const std::shared_ptr<MuonHoughHit>& hit, double weight) {
42 // MuonHough transform studies
43
44 // cylinder for extrapolation planes in muon system endcap/barrel transition
45
46 int sectorhit = sector(hit);
47
48 bool isbarrel = hit->isBarrel();
49
50 for (int i = 0; i < m_nbins / 2; i++) {
51 // not a too large curve for endcap hits (generates peaks in houghtransform)
52 const double ratio = hit->getMagneticTrackRatio() * m_invcurvature[i];
53 if (!isbarrel && std::abs(ratio) > 0.5) break;
54
55 // positive curvature (for positive i):
56 double thetas[2];
57 MuonHoughMathUtils::thetasForCurvedHit(ratio, hit.get(), thetas[0], thetas[1]);
58
59 const double weight_curvature =
60 weight * 1. /
61 (1. +
63 (thetas[0] -
64 hit->getTheta())); //* m_weightcurvature[i]; // m_eventsize_weightfactor is defined in MuonHoughTransformer::fill(event)
65
66 // Remove theta solutions outside 0 - 180 degree range
67 if (thetas[0] > 0. && thetas[0] < M_PI) {
68 double theta_in_grad = thetas[0] * MuonHough::rad_degree_conversion_factor;
69
70 const double weight_curvature_theta = weight_curvature * (0.5 + 0.5 * std::sin(thetas[0]));
71
72 fillHisto(i + 0.5, theta_in_grad, weight_curvature_theta, 2 * sectorhit); // overlap and single sector filling
73 }
74
75 // negative curvature (for negative i)
76
77 // Remove theta solutions outside 0 - 180 degree range
78 if (thetas[1] > 0. && thetas[1] < M_PI) {
79 double theta_in_grad = thetas[1] * MuonHough::rad_degree_conversion_factor;
80
81 const double weight_curvature_theta = weight_curvature * (0.5 + 0.5 * std::sin(thetas[1]));
82 fillHisto(-i - 0.5, theta_in_grad, weight_curvature_theta, 2 * sectorhit); // overlap and single sector filling
83 }
84 }
85}
86
87int MuonHoughTransformer_CurvedAtACylinder::fillHisto(double xbin, double theta_in_grad, double weight, int sector) {
88 MuonHoughHisto2D* histo = m_histos.getHisto(sector);
89
90 const int filled_binnumber = histo->fill(xbin, theta_in_grad, weight);
91
92 // overlap filling:
93 // overlap and single sector filling:
94 // nearby sectors:
95 if (m_number_of_sectors >= 3) {
96 const double reduced_weight = 0.8 * weight; // arbitrary should be between 0.5 and 1
97 if (sector != 0 && sector != m_number_of_sectors - 1) {
98 m_histos.getHisto(sector + 1)->fill(filled_binnumber, reduced_weight);
99 m_histos.getHisto(sector - 1)->fill(filled_binnumber, reduced_weight);
100 } else if (sector == 0) {
101 m_histos.getHisto(sector + 1)->fill(filled_binnumber, reduced_weight);
102 m_histos.getHisto(m_number_of_sectors - 1)->fill(filled_binnumber, reduced_weight);
103 } else {
104 m_histos.getHisto(sector - 1)->fill(filled_binnumber, reduced_weight);
105 m_histos.getHisto(0)->fill(filled_binnumber, reduced_weight);
106 }
107 }
108
109 // smearing effect:
110
111 const double fifth_weight = 0.2 * weight;
112 const int upperright = filled_binnumber + m_nbins_plus3;
113 const int lowerleft = filled_binnumber - m_nbins_plus3;
114
115 if (theta_in_grad - m_binwidthy < 0) {
116 histo->fill(upperright, fifth_weight);
117
118 if (m_use_negative_weights) { histo->fill(upperright - 2, -fifth_weight); }
119 } else if (theta_in_grad + m_binwidthy > 180.) {
120 histo->fill(lowerleft, fifth_weight);
121 if (m_use_negative_weights) { histo->fill(xbin + m_binwidthx, theta_in_grad - m_binwidthy, -fifth_weight); }
122 } else {
123 histo->fill(upperright, fifth_weight);
124 histo->fill(lowerleft, fifth_weight);
126 histo->fill(upperright - 2, -fifth_weight);
127 histo->fill(lowerleft + 2, -fifth_weight);
128 }
129 }
130 return filled_binnumber;
131}
132
134 std::pair<double, double> coordsmaximum,
135 double max_residu_mm, double /*max_residu_grad */,
136 int maxsector) const {
137 std::unique_ptr<MuonHoughPattern> houghpattern = std::make_unique<MuonHoughPattern>(MuonHough::hough_curved_at_a_cylinder);
138
139 // double ecurvature=0. // todo: recalculate estimated curvature for hits associated to maximum
140 double etheta{0.}, sin_phi{0.}, cos_phi{0.}, sin_theta{0.}, cos_theta{0.}, ephi{0.};
141 const double theta = m_muonhoughmathutils.angleFromGradToRadial(coordsmaximum.second);
142 double invcurvature{0.}, curvature{0.};
143 if (m_nbins < 40) {
144 curvature = MuonHoughMathUtils::sgn(coordsmaximum.first) / (coordsmaximum.first * coordsmaximum.first);
145 invcurvature = 1. / curvature;
146 } else {
147 // coordsmaximum.first = -80.5 .. 80.5 // 160 bins
148 int index = static_cast<int>(std::floor(std::abs(coordsmaximum.first)));
149 if (index >= m_nbins / 2) {
150 index = m_nbins / 2 - 1;
151 ATH_MSG_VERBOSE("warning overflow maximum found "<<index<<" vs. "<<m_nbins / 2 );
152 }
153 invcurvature = MuonHoughMathUtils::sgn(coordsmaximum.first) * m_invcurvature[index];
154 curvature = 1. / invcurvature;
155 }
156
157 // allowed sectors:
158 int sector_1 = maxsector / 2; // primary sector
159 int sector_2 = sector_1 + 1;
160 int sector_3 = sector_1 - 1;
161 if (sector_2 > m_number_of_sectors / 2 - 1) { sector_2 = 0; } // if sector_2 larger than 15 -> 0
162 if (maxsector % 2 == 1) { // if overlap maximum then only association to 2 sectors
163 sector_3 = sector_1;
164 } else if (sector_3 < 0) {
165 sector_3 = m_number_of_sectors / 2 - 1;
166 } // if sector_3 smaller than 0 -> 15
167
168 ATH_MSG_VERBOSE("sector: " << maxsector
169 << " coordsmaximumfirst: " << coordsmaximum.first << " curvature: " << curvature
170 << " coordsmaximumsecond: " << coordsmaximum.second << " coordsmaximumsecondinrad: " << theta
171 << " MuonHoughTransformer_CurvedAtACylinder::size of event: " << event.size()
172 << " allowed sectors: " << sector_1 << " , " << sector_2 << " & " << sector_3 );
173
174 for (unsigned int i = 0; i < event.size(); i++) {
175 std::shared_ptr<MuonHoughHit> hit = event.getHit(i);
176 int sectorhit = sector(hit);
177 if (sectorhit == sector_1 || sectorhit == sector_2 || sectorhit == sector_3) {
178 double z0{0.}; // offset from IP on z-axis
179 const double sdis = MuonHoughMathUtils::signedDistanceCurvedToHit(z0, theta, invcurvature, hit->getPosition());
180
181 double radius3d = std::min(15000.,std::max(5000.,hit->getAbs()));
182 double scale = radius3d / 5000.;
183
184 double residu_distance_mm = std::abs(sdis);
185
186
187 ATH_MSG_VERBOSE(" hit position " << hit->getPosition() <<" residu_distance: " << sdis
188 << " max_residu_mm*scale: " << max_residu_mm * scale);
189
190 if (std::abs(residu_distance_mm) < max_residu_mm * scale) // here no circular effect
191 {
192 double phi = hit->getPhi();
193 CxxUtils::sincos scphi(phi);
194 sin_phi += scphi.sn;
195 cos_phi += scphi.cs;
196
197 const double theta = MuonHoughMathUtils::thetaForCurvedHit(invcurvature, event.getHit(i).get());
198 if (theta > 0 && theta < M_PI) {
199 ATH_MSG_VERBOSE("hit added to houghpattern! Sector number: " << sectorhit
200 <<" associated earlier "<<event.getHit(i)->getAssociated());
201 houghpattern->addHit(event.getHit(i));
202 event.getHit(i)->setAssociated(true);
203 CxxUtils::sincos sctheta(theta);
204 sin_theta += sctheta.sn;
205 cos_theta += sctheta.cs;
206 }
207 } // residu
208 } // sector constraint
209 } // hitno
210
211 etheta = std::atan2(sin_theta, cos_theta);
212 // etheta = theta;
213 ephi = std::atan2(sin_phi, cos_phi);
214 houghpattern->setETheta(etheta);
215 houghpattern->setERTheta(0.);
216 houghpattern->setEPhi(ephi);
217 houghpattern->setECurvature(curvature);
218
219 ATH_MSG_VERBOSE(" number of hits added to pattern: " << houghpattern->size());
220 return houghpattern;
221}
222
224 // not in use for this transform
225 return 1.;
226}
#define M_PI
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_MSG_VERBOSE(x)
Histogram class, similar to Root's TH2D.
static void thetasForCurvedHit(double ratio, MuonHoughHit *hit, double &theta1, double &theta2)
calculates theta at (x,y,z) for curved track model, for positive and negative curvature
static double thetaForCurvedHit(double invcurvature, MuonHoughHit *hit)
calculates theta at (x,y,z) for curved track model
static int sgn(double d)
sign (-1 or 1) of a double
static double signedDistanceCurvedToHit(double z0, double theta, double invcurvature, const Amg::Vector3D &hit)
calculates distance of point (x,y,z) to curved track with z0, theta and invcurvature for curved track...
std::unique_ptr< MuonHoughPattern > hookAssociateHitsToMaximum(const MuonHoughHitContainer &event, std::pair< double, double > coordsmaximum, double residu_mm, double residu_grad, int sector) const override final
associate hits to maximum found
std::unique_ptr< double[]> m_invcurvature
array that stores the inverse curvatures that are scanned
MuonHoughTransformer_CurvedAtACylinder(int nbins, int nbins_angle, double detectorsize, double detectorsize_angle, double threshold_histo, int number_of_sectors=1)
constructor
float weightHoughTransform(double r0) const override final
not implemented for this transform
int sector(const std::shared_ptr< MuonHoughHit > &hit) const override final
returns the phi sector
int fillHisto(double xbin, double theta, double weight, int sector) override final
fill transformed values in histogram
void fillHit(const std::shared_ptr< MuonHoughHit > &hit, double weight) override final
fill hit in histogram
MuonHoughHisto2DContainer m_histos
histogram container
bool m_use_negative_weights
use of negative weights
bool m_add_weight_angle
use weight of patterns in angle coordinate
const int m_nbins
number of bins in histograms in radius coordinate
double m_weight_constant_radius
weight constant of patterns in radius coordinate
MuonHoughMathUtils m_muonhoughmathutils
object for use of mathematical formulas for trackmodels
const int m_number_of_sectors
number of histograms (1 for cosmics 16 for rz)
double m_eventsize_weightfactor
weightfactor based on eventsize (used in curved hough transform)
double m_binwidthx
x-binwidth of histogram
const int m_nbins_plus3
number of bins in histograms in radius coordinate
double m_binwidthy
y-binwidth of histogram
bool m_add_weight_radius
use weight of patterns in radius coordinate
MuonHoughTransformer(const std::string &tr_name, int nbins, int nbins_angle, double detectorsize, double detectorsize_angle, double threshold_histo, int number_of_sectors=1)
constructor, input values are those of histograms
singleton-like access to IMessageSvc via open function and helper
@ hough_curved_at_a_cylinder
constexpr double rad_degree_conversion_factor
Definition index.py:1
Helper to simultaneously calculate sin and cos of the same angle.
Helper to simultaneously calculate sin and cos of the same angle.
Definition sincos.h:39