10 #include "GaudiKernel/PhysicalConstants.h"
11 #include "GaudiKernel/SystemOfUnits.h"
13 #define DEFINE_VECTOR(dType, varName, nEles) \
14 std::vector<dType> varName{}; \
15 varName.reserve(nEles);
18 constexpr
double halfGapWidth = 2.52;
25 const IInterface*
p) :
27 declareInterface<IMMClusterBuilderTool>(
this);
33 return StatusCode::SUCCESS;
37 std::vector<MMPrepData>&& MMprds,
38 std::vector<std::unique_ptr<MMPrepData>>& clustersVec)
const {
42 for (std::vector<MMPrepData>& prdsOfLayer : prdsPerLayer) {
43 if (prdsOfLayer.size() < 2)
continue;
45 std::vector<std::vector<uint>> idxClusters =
clusterLayer(prdsOfLayer);
47 for (std::vector<uint>& clustIds : idxClusters) {
52 for (
unsigned idx : clustIds) {
56 const double q = toMerge.charge();
61 clusFeat.locPos = toMerge.localPosition();
62 clusFeat.distDrift = toMerge.driftDist();
63 clusFeat.resTransDistDrift = toMerge.localCovariance()(0, 0);
64 clusFeat.resLongDistDrift = toMerge.localCovariance()(1, 1);
67 stripFeatures.emplace_back(std::move(clusFeat));
68 clustConstituents.emplace_back(std::move(toMerge));
72 if (!errorCalibDB.isValid()) {
74 return StatusCode::FAILURE;
87 return StatusCode::SUCCESS;
98 int layer = 4 * (idHelper.multilayer(
id) - 1) + (idHelper.gasGap(
id) - 1);
99 prdsPerLayer.at(
layer).push_back(std::move(prd));
103 for (std::vector<MMPrepData>& prdsInLay : prdsPerLayer) {
105 return idHelper.channel(a.identify()) <
106 idHelper.channel(b.identify());
112 std::vector<std::vector<uint>>
117 int gasGap = idHelper.gasGap(MMPrdsPerLayer.at(0).identify());
121 for (
const auto& prd : MMPrdsPerLayer) {
123 <<
" local positionX " << prd.localPosition().x() <<
" time " << prd.time()
124 <<
" corrected time " << prd.time() <<
" angle to IP "<< prd.globalPosition().theta() <<
" "
128 std::vector<std::vector<uint>> idxClusters{};
130 idxClusters.push_back(std::vector<uint>{0});
131 for (
uint i_strip = 1; i_strip < MMPrdsPerLayer.size(); i_strip++) {
133 idxClusters.back().push_back(i_strip);
135 idxClusters.push_back(std::vector<uint>{i_strip});
139 ATH_MSG_DEBUG(
"Found " << idxClusters.size() <<
" clusters");
140 for (
const auto& idxCluster : idxClusters) {
ATH_MSG_DEBUG(
"cluster: " << idxCluster); }
145 std::pair<double, double>
148 const std::vector<NSWCalib::CalibratedStrip>& constituents,
152 double clusterPosition{0}, clusterPositionErrorSq{0.};
154 double qtot{0}, meanDriftDist{0.}, meanDriftDistError{0.};
155 double meanPosX{0.}, meanPosXError{0.};
158 const double driftDist = clustFeat.distDrift;
163 meanPosX += clustFeat.locPos.x() *
charge;
164 meanPosXError += clustFeat.resLongDistDrift * chargeSq;
165 meanDriftDist += driftDist *
charge;
166 meanDriftDistError += clustFeat.resTransDistDrift * chargeSq;
168 <<
" drift dist " << driftDist <<
" +- " << std::sqrt(clustFeat.resTransDistDrift)
169 <<
" xpos: "<< clustFeat.locPos.x() <<
" +- " << std::sqrt(clustFeat.resLongDistDrift)
170 <<
" xMeanPos " << meanPosX / qtot <<
" +- " << std::sqrt(meanPosXError) / qtot
171 <<
" meanPosXError " << meanPosXError <<
" meanDriftDist " << meanDriftDist / qtot
172 <<
" meanDriftDist Error " << std::sqrt(meanDriftDistError) / qtot
173 <<
" charge " <<
charge <<
" qtot " << qtot);
176 double meanPosXErrorSq = meanPosXError / (qtot * qtot);
177 meanDriftDist /= qtot;
178 double meanDriftDistErrorSq = meanDriftDistError / (qtot * qtot);
180 const double tanTheta =
std::tan(dirEstimate.theta());
181 double correction = tanTheta * (meanDriftDist - halfGapWidth);
185 double correctionErrorSq = tanTheta * tanTheta * meanDriftDistErrorSq;
188 clusterPositionErrorSq = correctionErrorSq + meanPosXErrorSq;
192 errorCalibIn.
stripId = constituents[0].identifier;
193 errorCalibIn.clusterAuthor =
author;
194 errorCalibIn.locPhi = dirEstimate.phi();
195 errorCalibIn.locTheta = dirEstimate.theta();
197 errorCalibIn.clusterSize = constituents.size();
202 <<
" meanX " << meanPosX <<
" +-" << std::sqrt(meanPosXErrorSq) <<
" mean drift dist " << meanDriftDist <<
" +- "
203 << std::sqrt(meanDriftDistErrorSq) <<
" correction " <<
correction <<
" +- " << std::sqrt(correctionErrorSq)
204 <<
" final position " << clusterPosition <<
" +- " << std::sqrt(clusterPositionErrorSq));
205 return std::make_pair(clusterPosition, localUncertainty*localUncertainty);
209 const std::vector<Muon::MMPrepData>& constituents,
210 const double clusterPosition,
211 const double clusterPositionErrorSq,
212 std::vector<std::unique_ptr<Muon::MMPrepData>>& mergedClust)
const {
223 rdoList.push_back(clustFeat.identify());
224 stripNumbers.push_back(
channel(clustFeat));
225 stripTimes.push_back(clustFeat.time());
226 stripCharges.push_back(clustFeat.charge());
227 stripDriftDists.push_back(clustFeat.driftDist());
229 stripDriftDistErrors.emplace_back(
cov(0,0),
cov(1,1));
230 totalCharge += clustFeat.charge();
235 covN.coeffRef(0, 0) = clusterPositionErrorSq;
236 Amg::Vector2D localClusterPositionV(clusterPosition, constituents[0].localPosition().
y());
237 Identifier idStrip0 = constituents[0].identify();
239 std::unique_ptr<MMPrepData> prdN = std::make_unique<MMPrepData>(idStrip0,
240 constituents[0].collectionHash(),
241 std::move(localClusterPositionV),
244 constituents[0].detectorElement(),
248 std::move(stripNumbers),
249 std::move(stripTimes),
250 std::move(stripCharges));
252 prdN->setDriftDist(std::move(stripDriftDists), std::move(stripDriftDistErrors));
255 mergedClust.push_back(std::move(prdN));
256 return StatusCode::SUCCESS;
260 const std::vector<NSWCalib::CalibratedStrip>& calibratedStrips,
266 if (!errorCalibDB.isValid()) {
268 return RIO_Author::unKnownAuthor;
271 constexpr
uint8_t toolAuthor =
static_cast<uint8_t>(RIO_Author::ClusterTimeProjectionClusterBuilder);
272 std::pair<double, double> posAndErrorSq =
getClusterPositionPRD(*errorCalibDB.cptr(), toolAuthor, calibratedStrips, directionEstimate);
274 clusterLocalPosition[
Trk::locX] = posAndErrorSq.first;
276 covN.coeffRef(0, 0) = posAndErrorSq.second;
279 return RIO_Author::ClusterTimeProjectionClusterBuilder;