ATLAS Offline Software
Loading...
Searching...
No Matches
Muon::STgcClusterBuilderCommon Class Reference

#include <STgcClusterBuilderCommon.h>

Inheritance diagram for Muon::STgcClusterBuilderCommon:
Collaboration diagram for Muon::STgcClusterBuilderCommon:

Public Member Functions

 STgcClusterBuilderCommon (const sTgcIdHelper &idHelper, const NswErrorCalibData &errorCalibData)
 Constructor.
std::array< std::vector< sTgcPrepData >, 8 > sortSTGCPrdPerLayer (std::vector< sTgcPrepData > &&stripPrds) const
 Separate the sTGC PRDs by layer, from 0 to 7, and sort the PRDs per layer in ascending order of strip number.
std::vector< std::vector< sTgcPrepData > > findStripCluster (std::vector< sTgcPrepData > &&strips, const int maxMissingStrip) const
 Find strip clusters, assuming the input vector of PRDs are sorted in ascending order of strip number.
std::optional< STgcClusterPositionweightedAverage (const std::vector< sTgcPrepData > &cluster, const double resolution, bool isStrip) const
 Compute the cluster position using the weighted average method.
std::optional< STgcClusterPositioncaruanaGaussianFitting (const std::vector< sTgcPrepData > &cluster, const double positionResolution, const double angularResolution, const MuonGM::MuonDetectorManager *detManager) const
 Method to fit analytically a cluster to a Gaussian function to obtain the position of the cluster The method supports only strip clusters having at least 3 strips.
bool msgLvl (const MSG::Level lvl) const
 Test the output level.
MsgStream & msg () const
 The standard message stream.
MsgStream & msg (const MSG::Level lvl) const
 The standard message stream.
void setLevel (MSG::Level lvl)
 Change the current logging level.

Private Member Functions

void initMessaging () const
 Initialize our message level and MessageSvc.

Private Attributes

const sTgcIdHelperm_stgcIdHelper
const NswErrorCalibDatam_errorCalibData
std::string m_nm
 Message source name.
boost::thread_specific_ptr< MsgStream > m_msg_tls
 MsgStream instance (a std::cout like with print-out levels)
std::atomic< IMessageSvc * > m_imsg { nullptr }
 MessageSvc pointer.
std::atomic< MSG::Level > m_lvl { MSG::NIL }
 Current logging level.
std::atomic_flag m_initialized ATLAS_THREAD_SAFE = ATOMIC_FLAG_INIT
 Messaging initialized (initMessaging)

Detailed Description

Definition at line 30 of file STgcClusterBuilderCommon.h.

Constructor & Destructor Documentation

◆ STgcClusterBuilderCommon()

Muon::STgcClusterBuilderCommon::STgcClusterBuilderCommon ( const sTgcIdHelper & idHelper,
const NswErrorCalibData & errorCalibData )

Constructor.

Definition at line 10 of file STgcClusterBuilderCommon.cxx.

11 : AthMessaging("STgcClusterBuilderCommon"),
12 m_stgcIdHelper(idHelper),
13 m_errorCalibData{errorCalibData}
14{
15}
AthMessaging()
Default constructor:
const NswErrorCalibData & m_errorCalibData

Member Function Documentation

◆ caruanaGaussianFitting()

std::optional< Muon::STgcClusterPosition > Muon::STgcClusterBuilderCommon::caruanaGaussianFitting ( const std::vector< sTgcPrepData > & cluster,
const double positionResolution,
const double angularResolution,
const MuonGM::MuonDetectorManager * detManager ) const

Method to fit analytically a cluster to a Gaussian function to obtain the position of the cluster The method supports only strip clusters having at least 3 strips.

A Gaussian function y(x) = A exp(-(x - \mu)^2 / (2 \sigma^2)) can be written as a quadratic function: ln(y(x)) = ln(A) - (x - \mu)^2 / (2 \sigma^2) = ln(A) - \mu^2 / (2 \sigma^2) - \mu x / \sigma^2 - x^2 / (2 \sigma^2) = a + b x + c x^2 where a = ln(A) - \mu^2 / (2 \sigma^2), b = -\mu / \sigma^2 and c = -1 / / (2 \sigma^2). Solving the equation, the mean position is \mu = -b / (2 c) and standard dev is \sigma = sqrt(-1 / (2 c)).

Parameters positionResolution and angularResolution enter in the estimate of the error on the mean position.

Definition at line 155 of file STgcClusterBuilderCommon.cxx.

160{
161
162 // Verify that there are 3 or more strips with non-zero charge, and the shape is not similar to a staircase
163 std::vector<int> charges;
164 charges.reserve(cluster.size());
165 std::vector<double> stripPositions;
166 stripPositions.reserve(cluster.size());
167 bool isStairUp{true}, isStairDown{true};
168 int multiplicity = 0;
169 for (unsigned int j = 0; j < cluster.size(); ++j){
170 int stripCharge = cluster.at(j).charge();
171 if (stripCharge > 0) {
172 multiplicity += 1;
173 charges.push_back(stripCharge);
174 stripPositions.push_back(cluster.at(j).localPosition().x());
175
176 if (j > 0) {
177 int prevStripCharge = cluster.at(j-1).charge();
178 if (isStairUp && (stripCharge - prevStripCharge < 0))
179 isStairUp = false;
180 if (isStairDown && (prevStripCharge > 0) && (stripCharge - prevStripCharge > 0))
181 isStairDown = false;
182 }
183 }
184 }
185
186 // Caruana fitting method doesn't support clusters having least than 3 strips or staircase-like clusters
187 if (multiplicity < 3 || isStairUp || isStairDown) {
188 if (msgLvl(MSG::VERBOSE)) {
189 std::stringstream sstr{};
190 for (const Muon::sTgcPrepData& prd : cluster) {
191 sstr << m_stgcIdHelper.print_to_string(prd.identify())
192 << ", local pos: ("<< prd.localPosition().x() << "," << prd.localPosition().y()
193 << "), charge: " << prd.charge() << ", time: " << static_cast<int>(prd.time())
194 << std::endl;
195 }
196 ATH_MSG_VERBOSE("Reject cluster incompatible with the Caruana method..." << std::endl << sstr.str());
197 }
198 return std::nullopt;
199 }
200
201 // Here we implement the Caruana method to reconstruct the position of the cluster
202 AmgSymMatrix(3) elementPosMatrix;
203 for (int i=0; i<3; i++) {
204 for (int j=0; j<=i; j++) elementPosMatrix.fillSymmetric(i, j, 0);
205 }
206 Amg::Vector3D chargeVector(0., 0., 0.);
207
208 // The reconstruction method becomes much simpiler when the strip positions are shifted such that
209 // the center of the cluster is at zero.
210 float clusterCenter = 0;
211 for (size_t i_strip = 0; i_strip < stripPositions.size(); i_strip++) {
212 clusterCenter += stripPositions.at(i_strip);
213 }
214 clusterCenter = clusterCenter / stripPositions.size();
215
216 std::vector<double> stripPositions_shifted = {};
217 for (size_t i_strip = 0; i_strip < stripPositions.size(); i_strip++) {
218 stripPositions_shifted.push_back(stripPositions.at(i_strip)-clusterCenter);
219 }
220
221 // Now build the matrix equation
222 for (size_t i_element = 0; i_element < stripPositions_shifted.size(); i_element++) {
223 elementPosMatrix.fillSymmetric(0, 0, elementPosMatrix(0,0) + 1);
224 elementPosMatrix.fillSymmetric(0, 1, elementPosMatrix(0,1) + stripPositions_shifted.at(i_element));
225 elementPosMatrix.fillSymmetric(0, 2, elementPosMatrix(0,2) + std::pow(stripPositions_shifted.at(i_element), 2));
226 elementPosMatrix.fillSymmetric(1, 2, elementPosMatrix(1,2) + std::pow(stripPositions_shifted.at(i_element), 3));
227 elementPosMatrix.fillSymmetric(2, 2, elementPosMatrix(2,2) + std::pow(stripPositions_shifted.at(i_element), 4));
228 const double log_charge = std::log(charges.at(i_element));
229 chargeVector(0) += log_charge;
230 chargeVector(1) += stripPositions_shifted.at(i_element) * log_charge;
231 chargeVector(2) += std::pow(stripPositions_shifted.at(i_element), 2) * log_charge;
232 }
233 elementPosMatrix(1,1) = elementPosMatrix(0,2);
234
235 // If the matrix is singular then the reconstruction method will fail
236 if (elementPosMatrix.determinant() == 0) {
237 if (msgLvl(MSG::VERBOSE)) {
238 std::stringstream sstr{};
239 for (const Muon::sTgcPrepData& prd : cluster) {
240 sstr << m_stgcIdHelper.print_to_string(prd.identify())
241 << ", local pos: ("<< prd.localPosition().x() << "," << prd.localPosition().y()
242 << "), charge: " << prd.charge() << ", time: " << static_cast<int>(prd.time())
243 << std::endl;
244 }
245 ATH_MSG_VERBOSE("Failed to compute the position of the cluster..." << std::endl << sstr.str());
246 }
247 return std::nullopt;
248 }
249
250 // Solve the matrix equation to find the Caruana parameters
251 Amg::Vector3D caruanaPars = (elementPosMatrix.inverse()) * chargeVector;
252
253 // The 3rd parameter is related to the standard deviation: sigma = sqrt(-1 / (2 * caruanaPars(2))).
254 // Hence use the Caruana method if the std dev is small i.e. < 3*strip_pitch or caruanaPars(2) > -0.005,
255 // or if std dev is not physical i.e. caruanaPars(2) >= 0
256 double reconstructedPosX{0.};
257 if (caruanaPars(2) < -0.005) {
258 reconstructedPosX = clusterCenter - caruanaPars(1) / (2*caruanaPars(2));
259 } else {
260 if (msgLvl(MSG::VERBOSE)) {
261 std::stringstream sstr{};
262 for (const Muon::sTgcPrepData& prd : cluster) {
263 sstr << m_stgcIdHelper.print_to_string(prd.identify())
264 << ", local pos: ("<< prd.localPosition().x() << "," << prd.localPosition().y()
265 << "), charge: " << prd.charge() << ", time: " << static_cast<int>(prd.time())
266 << std::endl;
267 }
268 ATH_MSG_VERBOSE("Reject cluster with large standard deviation..." << std::endl << sstr.str());
269 }
270 return std::nullopt;
271 }
272
273 // Find the channel that the cluster position reconstructs on top of and set the cluster id to its id
274 double minCenterDistance = 9999.99;
275 int channelIndex = 0;
276 for (size_t i_elem = 0; i_elem < cluster.size(); i_elem++) {
277 double strip_localPos = cluster.at(i_elem).localPosition().x();
278 if (minCenterDistance > abs(strip_localPos - reconstructedPosX)) {
279 minCenterDistance = abs(strip_localPos - reconstructedPosX);
280 channelIndex = i_elem;
281 }
282 }
283 const Identifier clusterId = cluster.at(channelIndex).identify();
284
285 // Get the sTGC readoutElement and the strip pitch
286 const MuonGM::sTgcReadoutElement* detEl = detManager->getsTgcReadoutElement(clusterId);
287 const double stripPitch = detEl->channelPitch(clusterId);
288
289 // If the reconstructed cluster position is far, such as one strip pitch, from any strip position in the cluster,
290 // then the Caruana reconstruction method isn't a good method to use.
291 if (minCenterDistance > stripPitch) {
292 if (msgLvl(MSG::VERBOSE)) {
293 std::stringstream sstr{};
294 for (const Muon::sTgcPrepData& prd : cluster) {
295 sstr << m_stgcIdHelper.print_to_string(prd.identify())
296 << ", local pos: ("<< prd.localPosition().x() << "," << prd.localPosition().y()
297 << "), charge: " << prd.charge() << ", time: " << static_cast<int>(prd.time())
298 << std::endl;
299 }
300 ATH_MSG_VERBOSE("Reject cluster since its position is more than " << stripPitch << " mm too far from the nearest strip..."
301 << std::endl << sstr.str());
302 }
303 return std::nullopt;
304 }
305
306 // We denote caruanaPars = (a, b, c) and find the error on the b and c components
307 double gamma0 = 0;
308 double gamma2 = 0;
309 double gamma4 = 0;
310 for (size_t i_strip = 0; i_strip < stripPositions_shifted.size(); i_strip++) {
311 gamma0 += 1;
312 gamma2 += std::pow(stripPositions_shifted.at(i_strip), 2);
313 gamma4 += std::pow(stripPositions_shifted.at(i_strip), 4);
314 }
315
316 // We also need the tan(theta) of the cluster
317 Amg::Vector3D globPos(0., 0., 0.);
318 detEl->stripGlobalPosition(clusterId, globPos);
319 double tan_theta = std::hypot(globPos.x(), globPos.y()) / globPos.z();
320 double spreadFactor = std::hypot(positionResolution, angularResolution * tan_theta);
321
322 double sigma_b = spreadFactor / std::sqrt(gamma2);
323 double sigma_c = spreadFactor * std::sqrt(gamma0 / (gamma0 * gamma4 - gamma2 * gamma2));
324
325 // Now propagate the Uncertainty to find the uncertainty on the mean
326 double sigmaSq = std::pow((1 / (2 * caruanaPars(2))) * sigma_b, 2) +
327 std::pow((caruanaPars(1) / (2 * caruanaPars(2) * caruanaPars(2))) * sigma_c, 2);
328
329 // Caruana method fails, if the uncertainty on the mean position is too large such as greater than 2mm
330 if (sigmaSq > 4) {
331 if (msgLvl(MSG::VERBOSE)) {
332 std::stringstream sstr{};
333 for (const Muon::sTgcPrepData& prd : cluster) {
334 sstr << m_stgcIdHelper.print_to_string(prd.identify())
335 << ", local pos: ("<< prd.localPosition().x() << "," << prd.localPosition().y()
336 << "), charge: " << prd.charge() << ", time: " << static_cast<int>(prd.time())
337 << std::endl;
338 }
339 ATH_MSG_VERBOSE("Reject cluster with large error on the mean position..." << std::endl << sstr.str());
340 }
341 return std::nullopt;
342 }
343
344
345 Amg::Vector3D globalClusterPos {detEl->surface(clusterId).transform()*Amg::Vector3D{reconstructedPosX, 0,0}};
346 Amg::Vector3D clusDir{ NswClustering::toLocal(detEl->surface(clusterId), globalClusterPos) };
347
348 NswErrorCalibData::Input errorCalibIn{};
349 errorCalibIn.stripId = clusterId;
350 errorCalibIn.clusterAuthor = static_cast<unsigned>(sTgcPrepData::Author::Caruana);
351 errorCalibIn.clusterError = std::sqrt(sigmaSq);
352 errorCalibIn.locPhi = clusDir.phi();
353 errorCalibIn.locTheta = clusDir.theta();
354 errorCalibIn.localPos = Amg::Vector2D{reconstructedPosX, 0};
355 errorCalibIn.clusterSize = cluster.size();
356
357 const double localUncertainty = m_errorCalibData.clusterUncertainty(errorCalibIn);
358
359 ATH_MSG_DEBUG("Reconstructed a cluster using the Caruana method,"
360 << " cluster Id: " << m_stgcIdHelper.print_to_string(clusterId)
361 << ", mean position = " << reconstructedPosX
362 << ", uncertainty = " << std::sqrt(sigmaSq));
363
364 return std::make_optional<Muon::STgcClusterPosition>(clusterId, reconstructedPosX, localUncertainty*localUncertainty);
365}
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
#define AmgSymMatrix(dim)
bool msgLvl(const MSG::Level lvl) const
Test the output level.
virtual const Trk::PlaneSurface & surface() const override
access to chamber surface (phi orientation), uses the first gas gap
const sTgcReadoutElement * getsTgcReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
double channelPitch(const Identifier &id) const
Channel pitch.
bool stripGlobalPosition(const Identifier &id, Amg::Vector3D &gpos) const
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
Amg::Vector3D toLocal(const Amg::Transform3D &toLocalTrans, const Amg::Vector3D &dir)
Rotates a direction vector into a local frame: x-axis : Parallell to the radial direction of the dete...
unsigned int clusterSize
Cluster size.
double locTheta
Direction of the muon in the local coordinate frame.
double clusterError
cluster error as calculated by the cluster builder tool
Amg::Vector2D localPos
Local position on the surface.
Identifier stripId
Identifier of the strip.
uint8_t clusterAuthor
Author of the cluster.
double locPhi
Azimuthal angle in the local frame.

◆ findStripCluster()

std::vector< std::vector< Muon::sTgcPrepData > > Muon::STgcClusterBuilderCommon::findStripCluster ( std::vector< sTgcPrepData > && strips,
const int maxMissingStrip ) const

Find strip clusters, assuming the input vector of PRDs are sorted in ascending order of strip number.

Definition at line 44 of file STgcClusterBuilderCommon.cxx.

45 {
46 std::vector<std::vector<Muon::sTgcPrepData>> clusters;
47
48 if (strips.empty()) return clusters;
49
50 // Get the Id of the first strip to verify all the strips are from the same layer
51 const Identifier& firstStripId = strips.front().identify();
52
53 for (Muon::sTgcPrepData& prd : strips) {
54 // If no element has been added to the vector of clusters yet
55 if (clusters.empty()) {
56 clusters.emplace_back();
57 clusters.back().push_back(std::move(prd));
58 continue;
59 }
60
61 const Identifier prd_id = prd.identify();
62 if (m_stgcIdHelper.multilayerID(firstStripId) != m_stgcIdHelper.multilayerID(prd_id) ||
63 m_stgcIdHelper.gasGap(firstStripId) != m_stgcIdHelper.gasGap(prd_id) ||
64 m_stgcIdHelper.channelType(firstStripId) != m_stgcIdHelper.channelType(prd_id)) {
65 ATH_MSG_WARNING("Strips must be separated by layer before attempting to build clusters,"
66 << " but found strips from different chambers");
67 continue;
68 }
69
70 // Add another strip to a vector of clusters
71 if (std::abs(m_stgcIdHelper.channel(prd.identify()) -
72 m_stgcIdHelper.channel(clusters.back().back().identify())) > maxMissingStrip + 1) {
73 clusters.emplace_back();
74 }
75 clusters.back().push_back(std::move(prd));
76 }
77
78 return clusters;
79}
#define ATH_MSG_WARNING(x)

◆ initMessaging()

void AthMessaging::initMessaging ( ) const
privateinherited

Initialize our message level and MessageSvc.

This method should only be called once.

Definition at line 39 of file AthMessaging.cxx.

40{
42 // If user did not set an explicit level, set a default
43 if (m_lvl == MSG::NIL) {
44 m_lvl = m_imsg ?
45 static_cast<MSG::Level>( m_imsg.load()->outputLevel(m_nm) ) :
46 MSG::INFO;
47 }
48}
std::string m_nm
Message source name.
std::atomic< IMessageSvc * > m_imsg
MessageSvc pointer.
std::atomic< MSG::Level > m_lvl
Current logging level.
IMessageSvc * getMessageSvc(bool quiet=false)

◆ msg() [1/2]

MsgStream & AthMessaging::msg ( ) const
inlineinherited

The standard message stream.

Returns a reference to the default message stream May not be invoked before sysInitialize() has been invoked.

Definition at line 163 of file AthMessaging.h.

164{
165 MsgStream* ms = m_msg_tls.get();
166 if (!ms) {
167 if (!m_initialized.test_and_set()) initMessaging();
168 ms = new MsgStream(m_imsg,m_nm);
169 m_msg_tls.reset( ms );
170 }
171
172 ms->setLevel (m_lvl);
173 return *ms;
174}
boost::thread_specific_ptr< MsgStream > m_msg_tls
MsgStream instance (a std::cout like with print-out levels)
void initMessaging() const
Initialize our message level and MessageSvc.

◆ msg() [2/2]

MsgStream & AthMessaging::msg ( const MSG::Level lvl) const
inlineinherited

The standard message stream.

Returns a reference to the default message stream May not be invoked before sysInitialize() has been invoked.

Definition at line 178 of file AthMessaging.h.

179{ return msg() << lvl; }
MsgStream & msg() const
The standard message stream.

◆ msgLvl()

bool AthMessaging::msgLvl ( const MSG::Level lvl) const
inlineinherited

Test the output level.

Parameters
lvlThe message level to test against
Returns
boolean Indicating if messages at given level will be printed
Return values
trueMessages at level "lvl" will be printed

Definition at line 151 of file AthMessaging.h.

152{
153 if (m_lvl <= lvl) {
154 msg() << lvl;
155 return true;
156 } else {
157 return false;
158 }
159}

◆ setLevel()

void AthMessaging::setLevel ( MSG::Level lvl)
inherited

Change the current logging level.

Use this rather than msg().setLevel() for proper operation with MT.

Definition at line 28 of file AthMessaging.cxx.

29{
30 m_lvl = lvl;
31}

◆ sortSTGCPrdPerLayer()

std::array< std::vector< Muon::sTgcPrepData >, 8 > Muon::STgcClusterBuilderCommon::sortSTGCPrdPerLayer ( std::vector< sTgcPrepData > && stripPrds) const

Separate the sTGC PRDs by layer, from 0 to 7, and sort the PRDs per layer in ascending order of strip number.

Definition at line 20 of file STgcClusterBuilderCommon.cxx.

20 {
21
22
23 std::array<std::vector<Muon::sTgcPrepData>, 8> stgcPrdsPerLayer;
24 for (Muon::sTgcPrepData& prd : stripPrds) {
25 const Identifier id = prd.identify();
26 int layer = 4 * (m_stgcIdHelper.multilayer(id) - 1) + (m_stgcIdHelper.gasGap(id) - 1);
27 ATH_MSG_DEBUG("Sorting PRD into layer, layer: " << layer << " gas_gap: " << m_stgcIdHelper.gasGap(id)
28 << "multilayer: " << m_stgcIdHelper.multilayer(id));
29 stgcPrdsPerLayer.at(layer).push_back(std::move(prd));
30 }
31
32 // sort prds by channel
33 for (unsigned int i_layer = 0; i_layer < stgcPrdsPerLayer.size(); i_layer++) {
34 std::sort(stgcPrdsPerLayer.at(i_layer).begin(), stgcPrdsPerLayer.at(i_layer).end(),
35 [this](const sTgcPrepData& a, const sTgcPrepData& b) {
36 return m_stgcIdHelper.channel(a.identify()) < m_stgcIdHelper.channel(b.identify());
37 });
38 }
39 return stgcPrdsPerLayer;
40}
static Double_t a
@ layer
Definition HitInfo.h:79
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.

◆ weightedAverage()

std::optional< Muon::STgcClusterPosition > Muon::STgcClusterBuilderCommon::weightedAverage ( const std::vector< sTgcPrepData > & cluster,
const double resolution,
bool isStrip ) const

Compute the cluster position using the weighted average method.

Definition at line 83 of file STgcClusterBuilderCommon.cxx.

87{
88
89 if (cluster.empty()) {
90 ATH_MSG_VERBOSE("Skipping empty cluster");
91 return std::nullopt;
92 }
93
94 double weightedPosX{0.0}, maxCharge{-1.0}, sumWeight{0.0}, sigmaSq{0.0};
95 Identifier clusterId;
96 Amg::Vector3D clusDir{Amg::Vector3D::Zero()};
97
98 ATH_MSG_DEBUG("Running weighted average method on a cluster with " << cluster.size() << " strips");
99 for (const Muon::sTgcPrepData& prd : cluster) {
100 // Skip channel if its charge is negative
101 if (prd.charge() < 0) continue;
102
103 double weight = isStrip ? prd.charge() : 1.0;
104 ATH_MSG_DEBUG("isStrip: " << isStrip << " weight: " << weight);
105
106 weightedPosX += prd.localPosition().x()*weight;
107 sumWeight += weight;
109 clusDir += weight * NswClustering::toLocal(prd);
110 ATH_MSG_DEBUG("Channel local position and charge: " << prd.localPosition().x() << " " << prd.charge() );
111
112 // Set the cluster identifier to the max charge strip
113 if (!isStrip) {
114 clusterId = prd.identify();
115 } else if (prd.charge() > maxCharge) {
116 maxCharge = prd.charge();
117 clusterId = prd.identify();
118 }
119 }
120
121 // Charge in PRD is an integer, so the sum of weights should be greater than 1 unless the data is corrupted.
122 // Skip corrupted cluster
123 if (sumWeight < 1) {
124 ATH_MSG_VERBOSE("Got unexpected sum of weights: " << sumWeight);
125 return std::nullopt;
126 }
127
128 // Mean position of the cluster
129 double reconstructedPosX = weightedPosX / sumWeight;
130 sigmaSq /= sumWeight;
131
132 NswErrorCalibData::Input errorCalibIn{};
133 errorCalibIn.stripId = clusterId;
134 errorCalibIn.clusterAuthor = static_cast<unsigned>(sTgcPrepData::Author::SimpleClusterBuilder);
135 errorCalibIn.locPhi = clusDir.phi();
136 errorCalibIn.locTheta = clusDir.theta();
137 errorCalibIn.localPos = Amg::Vector2D{reconstructedPosX, 0};
138 errorCalibIn.clusterSize = cluster.size();
139
140 const double localUncertainty = m_errorCalibData.clusterUncertainty(errorCalibIn);
141
142 ATH_MSG_VERBOSE("Reconstructed a cluster using the weighted average,"
143 << " cluster Id: " << m_stgcIdHelper.print_to_string(clusterId)
144 <<", direction: "<<Amg::toString(clusDir.unit())
145 <<", theta: "<<clusDir.theta() / Gaudi::Units::deg
146 << ", mean position = " << reconstructedPosX
147 << ", uncertainty = " << localUncertainty
148 <<", sigmaSQ: "<<sigmaSq);
149
150 return std::make_optional<Muon::STgcClusterPosition>(clusterId, reconstructedPosX, localUncertainty*localUncertainty);
151}
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
double resolution[nGasTypes][nParametersResolution]

Member Data Documentation

◆ ATLAS_THREAD_SAFE

std::atomic_flag m_initialized AthMessaging::ATLAS_THREAD_SAFE = ATOMIC_FLAG_INIT
mutableprivateinherited

Messaging initialized (initMessaging)

Definition at line 141 of file AthMessaging.h.

◆ m_errorCalibData

const NswErrorCalibData& Muon::STgcClusterBuilderCommon::m_errorCalibData
private

Definition at line 64 of file STgcClusterBuilderCommon.h.

◆ m_imsg

std::atomic<IMessageSvc*> AthMessaging::m_imsg { nullptr }
mutableprivateinherited

MessageSvc pointer.

Definition at line 135 of file AthMessaging.h.

135{ nullptr };

◆ m_lvl

std::atomic<MSG::Level> AthMessaging::m_lvl { MSG::NIL }
mutableprivateinherited

Current logging level.

Definition at line 138 of file AthMessaging.h.

138{ MSG::NIL };

◆ m_msg_tls

boost::thread_specific_ptr<MsgStream> AthMessaging::m_msg_tls
mutableprivateinherited

MsgStream instance (a std::cout like with print-out levels)

Definition at line 132 of file AthMessaging.h.

◆ m_nm

std::string AthMessaging::m_nm
privateinherited

Message source name.

Definition at line 129 of file AthMessaging.h.

◆ m_stgcIdHelper

const sTgcIdHelper& Muon::STgcClusterBuilderCommon::m_stgcIdHelper
private

Definition at line 63 of file STgcClusterBuilderCommon.h.


The documentation for this class was generated from the following files: