ATLAS Offline Software
ClusterTimeProjectionMMClusterBuilderTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
5 
6 #include <algorithm>
7 #include <numeric>
8 
10 #include "GaudiKernel/PhysicalConstants.h"
11 #include "GaudiKernel/SystemOfUnits.h"
12 
13 #define DEFINE_VECTOR(dType, varName, nEles) \
14  std::vector<dType> varName{}; \
15  varName.reserve(nEles);
16 
17 namespace {
18  constexpr double halfGapWidth = 2.52;
19 }
20 namespace Muon{
22 
24  const std::string& n,
25  const IInterface* p) :
26  AthAlgTool(t, n, p) {
27  declareInterface<IMMClusterBuilderTool>(this);
28 }
29 
31  ATH_CHECK(m_idHelperSvc.retrieve());
33  return StatusCode::SUCCESS;
34 }
35 
37  std::vector<MMPrepData>&& MMprds,
38  std::vector<std::unique_ptr<MMPrepData>>& clustersVec) const {
39  LaySortedPrds prdsPerLayer = sortHitsToLayer(std::move(MMprds));
40 
41 
42  for (std::vector<MMPrepData>& prdsOfLayer : prdsPerLayer) {
43  if (prdsOfLayer.size() < 2) continue; // require at least two strips per layer
44 
45  std::vector<std::vector<uint>> idxClusters = clusterLayer(prdsOfLayer);
46 
47  for (std::vector<uint>& clustIds : idxClusters) {
48  DEFINE_VECTOR(MMPrepData, clustConstituents, clustIds.size());
49  DEFINE_VECTOR(NSWCalib::CalibratedStrip, stripFeatures, clustIds.size());
50 
52  for (unsigned idx : clustIds) {
53  MMPrepData& toMerge{prdsOfLayer[idx]};
54 
55  const Amg::Vector3D lDir{NswClustering::toLocal(toMerge)};
56  const double q = toMerge.charge();
57 
58  clustDir += q * lDir;
59  NSWCalib::CalibratedStrip clusFeat{};
60  clusFeat.identifier = toMerge.identify();
61  clusFeat.locPos = toMerge.localPosition();
62  clusFeat.distDrift = toMerge.driftDist();
63  clusFeat.resTransDistDrift = toMerge.localCovariance()(0, 0);
64  clusFeat.resLongDistDrift = toMerge.localCovariance()(1, 1);
65  clusFeat.charge = q;
66 
67  stripFeatures.emplace_back(std::move(clusFeat));
68  clustConstituents.emplace_back(std::move(toMerge));
69  }
70 
72  if (!errorCalibDB.isValid()) {
73  ATH_MSG_FATAL("Failed to retrieve the parameterized errors "<<m_uncertCalibKey.fullKey());
74  return StatusCode::FAILURE;
75  }
76 
77  constexpr uint8_t toolAuthor = static_cast<uint8_t>(MMPrepData::Author::ClusterTimeProjectionClusterBuilder);
78  std::pair<double, double> posAndErrorSq = getClusterPositionPRD(**errorCalibDB,
79  toolAuthor,
80  stripFeatures,
81  clustDir.unit());
82 
83  ATH_CHECK(writeClusterPrd(ctx, clustConstituents, posAndErrorSq.first, posAndErrorSq.second, clustersVec));
84 
85  }
86  }
87  return StatusCode::SUCCESS;
88 }
89 
91  ClusterTimeProjectionMMClusterBuilderTool::sortHitsToLayer(std::vector<MMPrepData>&& MMprds) const {
92 
93  LaySortedPrds prdsPerLayer{};
94  const MmIdHelper& idHelper{m_idHelperSvc->mmIdHelper()};
95  // sorting hits by gas gap
96  for (MMPrepData& prd : MMprds) {
97  const Identifier id = prd.identify();
98  int layer = 4 * (idHelper.multilayer(id) - 1) + (idHelper.gasGap(id) - 1);
99  prdsPerLayer.at(layer).push_back(std::move(prd));
100  }
101  ATH_MSG_DEBUG("sorted hist");
102  // sort MMPrds by channel
103  for (std::vector<MMPrepData>& prdsInLay : prdsPerLayer) {
104  std::sort(prdsInLay.begin(), prdsInLay.end(), [&idHelper](const MMPrepData& a, const MMPrepData& b) {
105  return idHelper.channel(a.identify()) <
106  idHelper.channel(b.identify());
107  });
108  }
109  return prdsPerLayer;
110 }
111 
112  std::vector<std::vector<uint>>
113  ClusterTimeProjectionMMClusterBuilderTool::clusterLayer(const std::vector<MMPrepData>& MMPrdsPerLayer) const {
114 
115  const MmIdHelper& idHelper{m_idHelperSvc->mmIdHelper()};
116  // get gas gap for later correction of the sign of the slope
117  int gasGap = idHelper.gasGap(MMPrdsPerLayer.at(0).identify());
118 
119  ATH_MSG_DEBUG("Scanning gas gap " << gasGap);
120  if (msgLvl(MSG::VERBOSE)) {
121  for (const auto& prd : MMPrdsPerLayer) {
122  ATH_MSG_DEBUG("Hit channel " << " " << m_idHelperSvc->toStringDetEl(prd.identify())
123  << " local positionX " << prd.localPosition().x() << " time " << prd.time()
124  << " corrected time " << prd.time() << " angle to IP "<< prd.globalPosition().theta() << " "
125  << prd.globalPosition().theta() / Gaudi::Units::degree);
126  }
127  }
128  std::vector<std::vector<uint>> idxClusters{};
129  // simple grouping of strips using the fact that the strips where ordered by channel
130  idxClusters.push_back(std::vector<uint>{0}); // assumes that mmPrdsPerLayer always has at least one strip
131  for (uint i_strip = 1; i_strip < MMPrdsPerLayer.size(); i_strip++) {
132  if (channel(MMPrdsPerLayer.at(i_strip)) - channel(MMPrdsPerLayer.at(i_strip - 1)) <= m_maxHoleSize + 1) {
133  idxClusters.back().push_back(i_strip);
134  } else {
135  idxClusters.push_back(std::vector<uint>{i_strip});
136  }
137  }
138  if (msgLvl(MSG::VERBOSE)) {
139  ATH_MSG_DEBUG("Found " << idxClusters.size() << " clusters");
140  for (const auto& idxCluster : idxClusters) { ATH_MSG_DEBUG("cluster: " << idxCluster); }
141  }
142  return idxClusters;
143 } // end of cluster layer
144 
145 std::pair<double, double>
147  uint8_t author,
148  const std::vector<NSWCalib::CalibratedStrip>& constituents,
149  const Amg::Vector3D& dirEstimate) const {
150 
151 
152  double clusterPosition{0}, clusterPositionErrorSq{0.};
153 
154  double qtot{0}, meanDriftDist{0.}, meanDriftDistError{0.};
155  double meanPosX{0.}, meanPosXError{0.};
156 
157  for (const NSWCalib::CalibratedStrip& clustFeat : constituents) {
158  const double driftDist = clustFeat.distDrift;
160  const double charge = clustFeat.charge * Gaudi::Units::perThousand;
161  const double chargeSq = std::pow(charge, 2);
162  qtot += charge;
163  meanPosX += clustFeat.locPos.x() * charge;
164  meanPosXError += clustFeat.resLongDistDrift * chargeSq;
165  meanDriftDist += driftDist * charge;
166  meanDriftDistError += clustFeat.resTransDistDrift * chargeSq;
167  ATH_MSG_VERBOSE("Strip:"<<m_idHelperSvc->toString(clustFeat.identifier)
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);
174  }
175  meanPosX /= qtot;
176  double meanPosXErrorSq = meanPosXError / (qtot * qtot);
177  meanDriftDist /= qtot;
178  double meanDriftDistErrorSq = meanDriftDistError / (qtot * qtot);
179 
180  const double tanTheta = std::tan(dirEstimate.theta());
181  double correction = tanTheta * (meanDriftDist - halfGapWidth);
182  if (m_idHelperSvc->mmIdHelper().gasGap(constituents[0].identifier) % 2 == 0) {
183  correction = -1. * correction; // take care of inverted drif direction for even gaps
184  }
185  double correctionErrorSq = tanTheta * tanTheta * meanDriftDistErrorSq;
186 
187  clusterPosition = meanPosX + correction;
188  clusterPositionErrorSq = correctionErrorSq + meanPosXErrorSq;
189 
190 
191  NswErrorCalibData::Input errorCalibIn{};
192  errorCalibIn.stripId = constituents[0].identifier;
193  errorCalibIn.clusterAuthor = author;
194  errorCalibIn.locPhi = dirEstimate.phi();
195  errorCalibIn.locTheta = dirEstimate.theta();
196  errorCalibIn.localPos = Amg::Vector2D{clusterPosition, 0.};
197  errorCalibIn.clusterSize = constituents.size();
198 
199  const double localUncertainty = errorCalibDB.clusterUncertainty(errorCalibIn);
200 
201  ATH_MSG_DEBUG("Cluster Properties"
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);
206 }
207 
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 {
213 
214  DEFINE_VECTOR(Identifier, rdoList, constituents.size());
215  DEFINE_VECTOR(int, stripCharges, constituents.size());
216  DEFINE_VECTOR(short int, stripTimes, constituents.size());
217  DEFINE_VECTOR(uint16_t, stripNumbers, constituents.size());
218  DEFINE_VECTOR(float, stripDriftDists, constituents.size());
219  DEFINE_VECTOR(AmgVector(2), stripDriftDistErrors, constituents.size());
220 
221  int totalCharge{0};
222  for (const Muon::MMPrepData& clustFeat : constituents) {
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());
228  const Amg::MatrixX cov{clustFeat.localCovariance()};
229  stripDriftDistErrors.emplace_back(cov(0,0), cov(1,1));
230  totalCharge += clustFeat.charge();
231  }
232  if (!m_writeStripProperties) { stripNumbers.clear(); }
233 
234  auto covN = Amg::MatrixX(1, 1);
235  covN.coeffRef(0, 0) = clusterPositionErrorSq;
236  Amg::Vector2D localClusterPositionV(clusterPosition, constituents[0].localPosition().y());
237  Identifier idStrip0 = constituents[0].identify();
238 
239  std::unique_ptr<MMPrepData> prdN = std::make_unique<MMPrepData>(idStrip0,
240  constituents[0].collectionHash(),
241  std::move(localClusterPositionV),
242  std::move(rdoList),
243  std::move(covN),
244  constituents[0].detectorElement(),
245  0, // drift dist
246  totalCharge,
247  0.0 /*drift dist*/,
248  std::move(stripNumbers),
249  std::move(stripTimes),
250  std::move(stripCharges));
251 
252  prdN->setDriftDist(std::move(stripDriftDists), std::move(stripDriftDistErrors));
254 
255  mergedClust.push_back(std::move(prdN));
256  return StatusCode::SUCCESS;
257 }
258 
260  const std::vector<NSWCalib::CalibratedStrip>& calibratedStrips,
261  const Amg::Vector3D& directionEstimate,
262  Amg::Vector2D& clusterLocalPosition,
263  Amg::MatrixX& covMatrix) const{
264 
266  if (!errorCalibDB.isValid()) {
267  ATH_MSG_FATAL("Failed to retrieve the parameterized errors "<<m_uncertCalibKey.fullKey());
268  return RIO_Author::unKnownAuthor;
269  }
270 
271  constexpr uint8_t toolAuthor = static_cast<uint8_t>(RIO_Author::ClusterTimeProjectionClusterBuilder);
272  std::pair<double, double> posAndErrorSq = getClusterPositionPRD(*errorCalibDB.cptr(), toolAuthor, calibratedStrips, directionEstimate);
273 
274  clusterLocalPosition[Trk::locX] = posAndErrorSq.first;
275  Amg::MatrixX covN(1, 1);
276  covN.coeffRef(0, 0) = posAndErrorSq.second;
277  covMatrix = covN;
278 
279  return RIO_Author::ClusterTimeProjectionClusterBuilder;
280 }
281 }
282 #undef DEFINE_VECTOR
NswErrorCalibData
Definition: NswErrorCalibData.h:19
dumpTgcDigiDeadChambers.gasGap
list gasGap
Definition: dumpTgcDigiDeadChambers.py:33
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
Muon::MMPrepData
Class to represent MM measurements.
Definition: MMPrepData.h:22
Amg::MatrixX
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Definition: EventPrimitives.h:29
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
xAOD::uint8_t
uint8_t
Definition: Muon_v1.cxx:575
Trk::locX
@ locX
Definition: ParamDefs.h:43
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
EventPrimitivesHelpers.h
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
DEFINE_VECTOR
#define DEFINE_VECTOR(dType, varName, nEles)
Definition: ClusterTimeProjectionMMClusterBuilderTool.cxx:13
ClusterTimeProjectionMMClusterBuilderTool.h
plotBeamSpotVxVal.cov
cov
Definition: plotBeamSpotVxVal.py:201
AthCommonMsg< AlgTool >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
xAOD::identifier
identifier
Definition: UncalibratedMeasurement_v1.cxx:15
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Muon
This class provides conversion from CSC RDO data to CSC Digits.
Definition: TrackSystemController.h:49
Muon::ClusterTimeProjectionMMClusterBuilderTool::getClusters
StatusCode getClusters(const EventContext &ctx, std::vector< Muon::MMPrepData > &&stripsVect, std::vector< std::unique_ptr< Muon::MMPrepData >> &clustersVect) const override
Standard Interface to produce Micromega clusters from raw Input hits without external contstaint.
Definition: ClusterTimeProjectionMMClusterBuilderTool.cxx:36
Muon::IMMClusterBuilderTool::RIO_Author
MMClusterOnTrack::Author RIO_Author
Refinement of the cluster position after the cluster calibration loop is ran with a complete external...
Definition: IMMClusterBuilderTool.h:48
tools.zlumi_mc_cf.correction
def correction(mu, runmode, campaign, run=None)
Definition: zlumi_mc_cf.py:4
Muon::ClusterTimeProjectionMMClusterBuilderTool::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Muon Detector Descriptor.
Definition: ClusterTimeProjectionMMClusterBuilderTool.h:37
uint
unsigned int uint
Definition: LArOFPhaseFill.cxx:20
Muon::ClusterTimeProjectionMMClusterBuilderTool::m_maxHoleSize
Gaudi::Property< uint > m_maxHoleSize
Definition: ClusterTimeProjectionMMClusterBuilderTool.h:44
xAOD::uint16_t
setWord1 uint16_t
Definition: eFexEMRoI_v1.cxx:88
Identifier
Definition: DetectorDescription/Identifier/Identifier/Identifier.h:32
beamspotman.n
n
Definition: beamspotman.py:731
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
xAOD::covMatrix
covMatrix
Definition: TrackMeasurement_v1.cxx:19
AmgVector
AmgVector(4) T2BSTrackFilterTool
Definition: T2BSTrackFilterTool.cxx:114
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
Muon::ClusterTimeProjectionMMClusterBuilderTool::ClusterTimeProjectionMMClusterBuilderTool
ClusterTimeProjectionMMClusterBuilderTool(const std::string &, const std::string &, const IInterface *)
Definition: ClusterTimeProjectionMMClusterBuilderTool.cxx:23
python.SystemOfUnits.perThousand
float perThousand
Definition: SystemOfUnits.py:278
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
NswErrorCalibData::clusterUncertainty
double clusterUncertainty(const Input &clustInfo) const
Definition: NswErrorCalibData.cxx:95
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
NSWCalib::CalibratedStrip
Definition: INSWCalibTool.h:20
NswErrorCalibData::Input::stripId
Identifier stripId
Identifier of the strip.
Definition: NswErrorCalibData.h:27
Muon::ClusterTimeProjectionMMClusterBuilderTool::getCalibratedClusterPosition
virtual RIO_Author getCalibratedClusterPosition(const EventContext &ctx, const std::vector< NSWCalib::CalibratedStrip > &calibratedStrips, const Amg::Vector3D &directionEstimate, Amg::Vector2D &clusterLocalPosition, Amg::MatrixX &covMatrix) const override
Definition: ClusterTimeProjectionMMClusterBuilderTool.cxx:259
Muon::ClusterTimeProjectionMMClusterBuilderTool::channel
uint channel(const Identifier &id) const
Definition: ClusterTimeProjectionMMClusterBuilderTool.h:61
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
charge
double charge(const T &p)
Definition: AtlasPID.h:494
Muon::ClusterTimeProjectionMMClusterBuilderTool::sortHitsToLayer
LaySortedPrds sortHitsToLayer(std::vector< Muon::MMPrepData > &&MMprds) const
Definition: ClusterTimeProjectionMMClusterBuilderTool.cxx:91
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Muon::MMPrepData::Author::ClusterTimeProjectionClusterBuilder
@ ClusterTimeProjectionClusterBuilder
a
TList * a
Definition: liststreamerinfos.cxx:10
y
#define y
Muon::ClusterTimeProjectionMMClusterBuilderTool::getClusterPositionPRD
std::pair< double, double > getClusterPositionPRD(const NswErrorCalibData &errorCalibDB, uint8_t author, const std::vector< NSWCalib::CalibratedStrip > &features, const Amg::Vector3D &thetaEstimate) const
Definition: ClusterTimeProjectionMMClusterBuilderTool.cxx:146
MmIdHelper
Definition: MmIdHelper.h:54
Muon::ClusterTimeProjectionMMClusterBuilderTool::clusterLayer
std::vector< std::vector< uint > > clusterLayer(const std::vector< Muon::MMPrepData > &MMPrdsPerLayer) const
Definition: ClusterTimeProjectionMMClusterBuilderTool.cxx:113
CaloCondBlobAlgs_fillNoiseFromASCII.author
string author
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:26
Muon::ClusterTimeProjectionMMClusterBuilderTool::m_uncertCalibKey
SG::ReadCondHandleKey< NswErrorCalibData > m_uncertCalibKey
Definition: ClusterTimeProjectionMMClusterBuilderTool.h:40
Muon::NswClustering::toLocal
Amg::Vector3D toLocal(const Trk::Surface &surf, const Amg::Vector3D &dir)
Rotates a direction vector into a local frame: x-axis : Parallell to the radial direction of the dete...
Definition: NswClusteringUtils.h:21
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
extractSporadic.q
list q
Definition: extractSporadic.py:98
NswErrorCalibData::Input
Helper struct to be parsed to the object to derive the specific error of the cluster.
Definition: NswErrorCalibData.h:25
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
AthAlgTool
Definition: AthAlgTool.h:26
Muon::ClusterTimeProjectionMMClusterBuilderTool::m_writeStripProperties
Gaudi::Property< bool > m_writeStripProperties
Definition: ClusterTimeProjectionMMClusterBuilderTool.h:43
Muon::MMClusterOnTrack::Author
Author
Definition: MMClusterOnTrack.h:89
Muon::ClusterTimeProjectionMMClusterBuilderTool::writeClusterPrd
StatusCode writeClusterPrd(const EventContext &ctx, const std::vector< Muon::MMPrepData > &constituents, const double clustersPosition, const double clustersPositionErrorSq, std::vector< std::unique_ptr< Muon::MMPrepData >> &mergedClust) const
Definition: ClusterTimeProjectionMMClusterBuilderTool.cxx:208
Muon::ClusterTimeProjectionMMClusterBuilderTool::initialize
StatusCode initialize() override
Definition: ClusterTimeProjectionMMClusterBuilderTool.cxx:30
Muon::ClusterTimeProjectionMMClusterBuilderTool::LaySortedPrds
std::array< std::vector< Muon::MMPrepData >, 8 > LaySortedPrds
Definition: ClusterTimeProjectionMMClusterBuilderTool.h:35
python.SystemOfUnits.degree
tuple degree
Definition: SystemOfUnits.py:106
generate::Zero
void Zero(TH1D *hin)
Definition: generate.cxx:32
NSWCalib::CalibratedStrip::identifier
Identifier identifier
Definition: INSWCalibTool.h:29