ATLAS Offline Software
MmRdoToPrepDataToolMT.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
11 
12 // BS access
16 using namespace MuonGM;
17 using namespace Trk;
18 
19 namespace {
20  // Count hits with negative charge, which indicates bad calibration
21  std::atomic<bool> hitNegativeCharge{false};
22 } // namespace
23 
24 namespace Muon{
25 
27  ATH_MSG_DEBUG(" in initialize()");
28  ATH_CHECK(m_idHelperSvc.retrieve());
29  // check if the initialization of the data container is success
30  ATH_CHECK(m_writeKey.initialize());
31  ATH_CHECK(m_readKey.initialize());
32  ATH_CHECK(m_muDetMgrKey.initialize());
33  ATH_CHECK(m_calibTool.retrieve());
34  ATH_CHECK(m_updateKey.initialize(!m_updateKey.key().empty()));
35  ATH_CHECK(m_xAODKey.initialize(!m_xAODKey.empty()));
36  return StatusCode::SUCCESS;
37 }
38 
39 StatusCode MmRdoToPrepDataToolMT::processCollection(const EventContext& ctx,
40  MMPrepDataContainer* mmPrepDataContainer,
41  xAOD::MMClusterContainer* xAODContainer,
42  const std::vector<IdentifierHash>& idsToDecode,
43  const MM_RawDataCollection* rdoColl) const {
44  ATH_MSG_DEBUG(" ***************** Start of process MM Collection");
45  const MmIdHelper& id_helper = m_idHelperSvc->mmIdHelper();
46  // protect for large splashes
47  bool merge = m_merge || rdoColl->size() > 100;
48 
49  const IdentifierHash hash = rdoColl->identifierHash();
50 
51  // check if we actually want to decode this RDO collection
52  if (!idsToDecode.empty() and std::find(idsToDecode.begin(), idsToDecode.end(),
53  hash) == idsToDecode.end()) {
54  ATH_MSG_DEBUG("Hash ID " << hash << " not in input list, ignore");
55  return StatusCode::SUCCESS;
56  } else
57  ATH_MSG_DEBUG("Going to decode " << hash);
58 
59  // check if the collection already exists, otherwise add it
60  if (mmPrepDataContainer->indexFindPtr(hash) != nullptr) {
61 
62  ATH_MSG_DEBUG("In processCollection: collection already contained in the MM PrepData container");
63  return StatusCode::SUCCESS;
64  }
65 
66  // Get write handle for this collection
68  // Check if collection already exists (via the cache, i.e. in online trigger
69  // mode)
70  if (lock.OnlineAndPresentInAnotherView()) {
71  ATH_MSG_DEBUG("In processCollection: collection already available in the MM PrepData container (via cache)");
72  return StatusCode::SUCCESS;
73  }
74  auto prdColl = std::make_unique<MMPrepDataCollection>(hash);
75 
76  // set the offline identifier of the collection Id
77  IdContext context = id_helper.module_context();
78  Identifier moduleId{};
79  if (id_helper.get_id(hash, moduleId, &context) != 0) {
80  ATH_MSG_ERROR("Could not convert the hash Id: " << hash << " to identifier");
81  } else {
82  ATH_MSG_DEBUG(" dump moduleId " << moduleId);
83  prdColl->setIdentifier(moduleId);
84  }
85 
86  // MuonDetectorManager from the conditions store
87  SG::ReadCondHandle<MuonGM::MuonDetectorManager> MuonDetMgr{m_muDetMgrKey, ctx};
88  if (!MuonDetMgr.isValid()) {
89  ATH_MSG_ERROR("Null pointer to the read MuonDetectorManager conditions object");
90  return StatusCode::FAILURE;
91  }
92 
93  std::vector<MMPrepData> MMprds;
94  // convert the RDO collection to a PRD collection
95  for (const MM_RawData* rdo : *rdoColl) {
96  ATH_MSG_DEBUG("Adding a new MM PrepRawData");
97 
98  const Identifier rdoId = rdo->identify();
99  // ATH_MSG_ALWAYS(" dump rdo " << m_idHelperSvc->toString(rdoId) << " pdo " << rdo->charge()
100  // << " time " << rdo->time() << " relBCID " << rdo->relBcid());
101 
102  int channel = rdo->channel();
103  std::vector<Identifier> rdoList;
104  Identifier prdId = id_helper.channelID(rdoId, id_helper.multilayer(rdoId), id_helper.gasGap(rdoId), channel);
105  ATH_MSG_DEBUG(" channel RDO " << channel << " channel from rdoID " << id_helper.channel(rdoId));
106  rdoList.push_back(prdId);
107 
108  // get the local and global positions
109  const MuonGM::MMReadoutElement* detEl = MuonDetMgr->getMMReadoutElement(prdId);
111 
112  bool getLocalPos = detEl->stripPosition(prdId, localPos);
113  if (!getLocalPos) {
114  if (msgLvl(MSG::DEBUG)) { // We should still keep this a warning and fix it properly but silence it for now (ATLASRECTS-7520)
115  ATH_MSG_WARNING("Could not get the local strip position for "<< m_idHelperSvc->toString(prdId));
116  }
117  continue;
118  }
119 
120  Amg::Vector3D globalPos{Amg::Vector3D::Zero()};
121  bool getGlobalPos = detEl->stripGlobalPosition(prdId, globalPos);
122  if (!getGlobalPos) {
123  ATH_MSG_WARNING("Could not get the global strip position for MM");
124  continue;
125  }
126  NSWCalib::CalibratedStrip calibStrip;
127  ATH_CHECK(m_calibTool->calibrateStrip(ctx, rdo, calibStrip));
128  if (calibStrip.charge < 0) {
129  if (!hitNegativeCharge || msgLvl(MSG::DEBUG)) {
130  ATH_MSG_DEBUG("One MM RDO or more, such as one with pdo = "<< rdo->charge()
131  << " counts, corresponds to a negative charge ("<< calibStrip.charge << "). Skipping these RDOs");
132  hitNegativeCharge = true;
133  }
134  continue;
135  }
136 
137  Trk::LocalDirection localDir;
138  const Trk::PlaneSurface& psurf = detEl->surface(prdId);
140  psurf.globalToLocal(globalPos, globalPos, lpos);
141  psurf.globalToLocalDirection(globalPos, localDir);
142 
143  ATH_MSG_DEBUG(" Surface centre x " << Amg::toString(psurf.center()));
144  ATH_MSG_DEBUG(" localPos x " <<Amg::toString(localPos)<< " localPos y " << Amg::toString(lpos));
145 
146  Amg::Vector3D gdir = psurf.transform().linear() * Amg::Vector3D::UnitY();
147  ATH_MSG_DEBUG(" MM detector surface direction phi "<< gdir.phi() << " global radius hit " << globalPos.perp()
148  << " phi pos " << globalPos.phi() << " global z "<< globalPos.z());
149 
150  auto cov = Amg::MatrixX(2, 2);
151  cov.setIdentity();
152  (cov)(0, 0) = calibStrip.resTransDistDrift;
153  (cov)(1, 1) = calibStrip.resLongDistDrift;
154  localPos.x() += calibStrip.dx;
155 
156  if (!merge) {
157  // storage will be handeled by Store Gate
158  auto mpd = std::make_unique<MMPrepData>(prdId, hash,
159  std::move(localPos), std::move(rdoList), std::move(cov),
160  detEl,
161  calibStrip.time, calibStrip.charge, calibStrip.distDrift);
162  mpd->setAuthor(MMPrepData::Author::RDOTOPRDConverter);
163 
164  prdColl->push_back(std::move(mpd));
165 
166  } else {
167  if (calibStrip.charge < m_singleStripChargeCut) {
168  // ATH_MSG_ALWAYS("Strip with charge " << calibStrip.charge << " below the cut of " << m_singleStripChargeCut << ", skipping it");
169  continue;
170  }
171  // ATH_MSG_ALWAYS("producing prd with charge " << calibStrip.charge << " time " << calibStrip.time);
172  MMPrepData mpd(prdId, hash, std::move(localPos), std::move(rdoList),
173  std::move(cov), detEl, calibStrip.time, calibStrip.charge,
174  calibStrip.distDrift);
175  // set the hash of the MMPrepData such that it contains the correct value
176  // in case it gets used in SimpleMMClusterBuilderTool::getClusters
177  mpd.setHashAndIndex(hash, 0);
178  mpd.setAuthor(MMPrepData::Author::RDOTOPRDConverter);
179  MMprds.push_back(std::move(mpd));
180  }
181  }
182 
183  if (merge) {
184  std::vector<std::unique_ptr<MMPrepData>> clusters;
185 
187  ATH_CHECK(m_clusterBuilderTool->getClusters(ctx, std::move(MMprds), clusters));
188 
189  for (std::unique_ptr<MMPrepData>& prdN : clusters) {
190  prdN->setHashAndIndex(prdColl->identifyHash(), prdColl->size());
191  prdColl->push_back(std::move(prdN));
192  }
193  } // merge
194 
195  if (xAODContainer) {
196  // Lambda to fill xprd from prd
197  std::vector<const MMPrepData*> sortMe{prdColl->begin(), prdColl->end()};
198  std::ranges::sort(sortMe, IdentifierByDetElSorter{m_idHelperSvc.get()});
199  for (const MMPrepData* prd : sortMe) {
200  xAOD::MMCluster* cluster{xAODContainer->push_back(std::make_unique<xAOD::MMCluster>())};
201  cluster->setIdentifier(prd->identify().get_compact());
202  cluster->setMeasurement(m_idHelperSvc->detElementHash(prd->identify()),
203  xAOD::MeasVector<1>{prd->localPosition().x()},
204  xAOD::MeasMatrix<1>{prd->localCovariance()(0, 0)});
205  cluster->setGasGap(id_helper.gasGap(prd->identify()));
206  cluster->setChannelNumber(id_helper.channel(prd->identify()));
207  cluster->setTime(prd->time());
208  cluster->setCharge(prd->charge());
209  cluster->setDriftDist(prd->driftDist());
210  cluster->setAngle(prd->angle());
211  cluster->setChiSqProb(prd->chisqProb());
212  cluster->setAuthor(prd->author());
213  cluster->setQuality(prd->quality());
214  cluster->setStripNumbers(prd->stripNumbers());
215  cluster->setStripTimes(prd->stripTimes());
216  cluster->setStripCharges(prd->stripCharges());
217  cluster->setStripDriftDist(prd->stripDriftDist());
218  cluster->setStripDriftErrors(prd->stripDriftErrors());
219  }
220  }
221  // now write the collection
222  ATH_CHECK(lock.addOrDelete(std::move(prdColl)));
223  ATH_MSG_DEBUG("PRD hash " << hash << " has been moved to container");
224 
225  return StatusCode::SUCCESS;
226 }
227 
228 const MM_RawDataContainer*
229  MmRdoToPrepDataToolMT::getRdoContainer(const EventContext& ctx) const {
230  auto rdoContainerHandle = SG::makeHandle(m_readKey, ctx);
231  if (rdoContainerHandle.isValid()) {
232  ATH_MSG_DEBUG("MM_getRdoContainer success");
233  return rdoContainerHandle.cptr();
234  }
235  ATH_MSG_WARNING("Retrieval of MM_RawDataContainer failed !");
236 
237  return nullptr;
238 }
239 
240 void MmRdoToPrepDataToolMT::processRDOContainer(const EventContext& ctx,
241  MMPrepDataContainer* mmPrepDataContainer,
242  xAOD::MMClusterContainer* xAODContainer,
243  const std::vector<IdentifierHash>& idsToDecode) const {
244  ATH_MSG_DEBUG("In processRDOContainer");
245  const MM_RawDataContainer* rdoContainer = getRdoContainer(ctx);
246  if (!rdoContainer) {
247  return;
248  }
249 
250  for (const MM_RawDataCollection* rdoColl : *rdoContainer) {
251 
252  if (rdoColl->empty()){
253  continue;
254  }
255  ATH_MSG_DEBUG("New RDO collection with " << rdoColl->size() << "MM Hits");
256 
257  if (processCollection(ctx, mmPrepDataContainer, xAODContainer, idsToDecode, rdoColl).isFailure()) {
259  "processCsm returns a bad StatusCode - keep going for new data "
260  "collections in this event");
261  }
262  }
263 }
264 
265 // methods for ROB-based decoding
266 StatusCode MmRdoToPrepDataToolMT::decode(const EventContext& ctx,
267  const std::vector<IdentifierHash>& idVect) const {
268 
269  // is idVect a right thing to use here? to be reviewed maybe
270  ATH_MSG_DEBUG("Size of the RDO container to be decoded: " << idVect.size());
271 
272  MMPrepDataContainer* mmPrepDataContainer = setupMM_PrepDataContainer(ctx);
273 
274  if (!mmPrepDataContainer) {
275  return StatusCode::FAILURE;
276  }
277 
279  xAOD::MMClusterContainer* xAODContainer{nullptr};
280  if (!m_xAODKey.empty()) {
281  outputContainer = SG::WriteHandle{m_xAODKey, ctx};
282  ATH_CHECK(outputContainer.record(std::make_unique<xAOD::MMClusterContainer>(),
283  std::make_unique<xAOD::MMClusterAuxContainer>()));
284  xAODContainer = outputContainer.ptr();
285  }
286 
287  processRDOContainer(ctx, mmPrepDataContainer, xAODContainer, idVect);
288 
289  return StatusCode::SUCCESS;
290 }
291 
293  const std::vector<uint32_t>&) const {
294  ATH_MSG_FATAL("ROB based decoding is not supported....");
295  return StatusCode::FAILURE;
296 }
297 StatusCode MmRdoToPrepDataToolMT::provideEmptyContainer(const EventContext& ctx) const {
298  if (!m_xAODKey.empty()) {
299  SG::WriteHandle writeHandle{m_xAODKey, ctx};
300  ATH_CHECK(writeHandle.record(std::make_unique<xAOD::MMClusterContainer>(),
301  std::make_unique<xAOD::MMClusterAuxContainer>()));
302  }
303 
304  return setupMM_PrepDataContainer(ctx) ? StatusCode::SUCCESS
305  : StatusCode::FAILURE;
306 }
307 
309 MmRdoToPrepDataToolMT::setupMM_PrepDataContainer(const EventContext& ctx) const {
310 
311  SG::WriteHandle handle{m_writeKey, ctx};
312  if (m_updateKey.key().empty()) {
313  // No external cache, just record the container
315  handle.record(std::make_unique<MMPrepDataContainer>(
316  m_idHelperSvc->mmIdHelper().module_hash_max()));
317 
318  if (status.isFailure() || !handle.isValid()) {
320  "Could not record container of MicroMega PrepData Container at "
321  << m_writeKey.key());
322  return nullptr;
323  }
324  } else {
325  // use the cache to get the container
326  SG::UpdateHandle update(m_updateKey, ctx);
327  if (!update.isValid()) {
328  ATH_MSG_FATAL("Invalid UpdateHandle " << m_updateKey.key());
329  return nullptr;
330  }
331  StatusCode status = handle.record(std::make_unique<MMPrepDataContainer>(update.ptr()));
332  if (status.isFailure() || !handle.isValid()) {
334  "Could not record container of MM PrepData Container using cache "
335  << m_updateKey.key() << " - "
336  << m_writeKey.key());
337  return nullptr;
338  }
339  ATH_MSG_DEBUG("Created container using cache for "
340  << m_updateKey.key());
341  }
342  return handle.ptr();
343 }
344 
345 }
MuonGM::MMReadoutElement::stripPosition
virtual bool stripPosition(const Identifier &id, Amg::Vector2D &pos) const override final
strip position – local or global If the strip number is outside the range of valid strips,...
Definition: MMReadoutElement.h:206
AtlasMcWeight::decode
double decode(number_type binnedWeight)
Convert weight from unsigned to double.
Definition: AtlasMcWeight.cxx:32
Trk::PlaneSurface::globalToLocal
virtual bool globalToLocal(const Amg::Vector3D &glob, const Amg::Vector3D &mom, Amg::Vector2D &loc) const override final
Specified for PlaneSurface: GlobalToLocal method without dynamic memory allocation - boolean checks i...
Definition: PlaneSurface.cxx:209
Muon::MuonPrepDataContainer
Template for Muon PRD containers (which are basically collections of MuonPrepDataCollections).
Definition: MuonPrepDataContainer.h:42
NSWCalib::CalibratedStrip::time
double time
Definition: INSWCalibTool.h:26
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
MuonGM
Ensure that the Athena extensions are properly loaded.
Definition: GeoMuonHits.h:27
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:27
NSWCalib::CalibratedStrip::charge
double charge
Definition: INSWCalibTool.h:25
plotting.yearwise_efficiency.channel
channel
Definition: yearwise_efficiency.py:24
MuonIdHelper::get_id
virtual int get_id(const IdentifierHash &hash_id, Identifier &id, const IdContext *context=0) const override
Create compact id from hash id (return == 0 for OK)
Definition: MuonIdHelper.cxx:70
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
xAOD::MMCluster_v1
Definition: MMCluster_v1.h:20
NSWCalib::CalibratedStrip::distDrift
double distDrift
Definition: INSWCalibTool.h:28
IdentifiableContainerMT::getWriteHandle
IDC_WriteHandle getWriteHandle(IdentifierHash hash)
Definition: IdentifiableContainerMT.h:248
NSWCalib::CalibratedStrip::dx
double dx
Definition: INSWCalibTool.h:31
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
initialize
void initialize()
Definition: run_EoverP.cxx:894
IMuonRawDataProviderTool.h
plotBeamSpotVxVal.cov
cov
Definition: plotBeamSpotVxVal.py:200
NSWCalib::CalibratedStrip::resTransDistDrift
double resTransDistDrift
Definition: INSWCalibTool.h:29
MMPrepDataContainer.h
python.RatesEmulationExample.lock
lock
Definition: RatesEmulationExample.py:148
Trk::Surface::center
const Amg::Vector3D & center() const
Returns the center position of the Surface.
Muon
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
Definition: TrackSystemController.h:45
NSWCalib::CalibratedStrip::resLongDistDrift
double resLongDistDrift
Definition: INSWCalibTool.h:30
MuonGM::MuonClusterReadoutElement::surface
virtual const Trk::PlaneSurface & surface() const override
access to chamber surface (phi orientation), uses the first gas gap
Definition: MuonClusterReadoutElement.h:123
Muon::MM_RawDataCollection
Definition: MM_RawDataCollection.h:15
Muon::MM_RawDataContainer
Definition: MM_RawDataContainer.h:18
MmIdHelper::multilayer
int multilayer(const Identifier &id) const
Definition: MmIdHelper.cxx:796
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:274
MMReadoutElement.h
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
MMClusterAuxContainer.h
Trk::PrepRawData::setHashAndIndex
void setHashAndIndex(unsigned short collHash, unsigned short objIndex)
TEMP for testing: might make some classes friends later ...
Muon::MM_RawData
Temporary class to hold the MM RDO.
Definition: MM_RawData.h:20
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
MuonGM::MMReadoutElement::stripGlobalPosition
bool stripGlobalPosition(const Identifier &id, Amg::Vector3D &gpos) const
Definition: MMReadoutElement.h:277
IdentifiableContainerMT::IDC_WriteHandle
Definition: IdentifiableContainerMT.h:34
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
MmRdoToPrepDataToolMT.h
Trk::PlaneSurface::globalToLocalDirection
void globalToLocalDirection(const Amg::Vector3D &glodir, Trk::LocalDirection &locdir) const
This method transforms the global direction to a local direction wrt the plane.
Definition: PlaneSurface.cxx:256
Muon::MM_RawDataCollection::identifierHash
const IdentifierHash & identifierHash() const
Definition: MM_RawDataCollection.h:23
NSWCalib::CalibratedStrip
Definition: INSWCalibTool.h:24
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
Trk::LocalDirection
represents the three-dimensional global direction with respect to a planar surface frame.
Definition: LocalDirection.h:81
xAOD::MeasVector
Eigen::Matrix< float, N, 1 > MeasVector
Abrivation of the Matrix & Covariance definitions.
Definition: MeasurementDefs.h:53
Trk
Ensure that the ATLAS eigen extensions are properly loaded.
Definition: FakeTrackBuilder.h:9
SG::UpdateHandle
Definition: UpdateHandle.h:91
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
IdentifiableContainerMT::indexFindPtr
virtual const T * indexFindPtr(IdentifierHash hashId) const override final
return pointer on the found entry or null if out of range using hashed index - fast version,...
Definition: IdentifiableContainerMT.h:289
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:73
MmIdHelper::channel
int channel(const Identifier &id) const override
Definition: MmIdHelper.cxx:800
MmIdHelper
Definition: MmIdHelper.h:54
MmIdHelper::gasGap
int gasGap(const Identifier &id) const override
get the hashes
Definition: MmIdHelper.cxx:798
CaloCondBlobAlgs_fillNoiseFromASCII.hash
dictionary hash
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:108
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Trk::PlaneSurface
Definition: PlaneSurface.h:64
DEBUG
#define DEBUG
Definition: page_access.h:11
RunTileMonitoring.clusters
clusters
Definition: RunTileMonitoring.py:133
MuonIdHelper::module_context
IdContext module_context() const
id for module
Definition: MuonIdHelper.cxx:737
MuonGM::MMReadoutElement
An MMReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station con...
Definition: MMReadoutElement.h:25
merge.status
status
Definition: merge.py:16
IdentifierByDetElSorter.h
LocalDirection.h
xAOD::MeasMatrix
Eigen::Matrix< float, N, N > MeasMatrix
Definition: MeasurementDefs.h:55
Muon::IdentifierByDetElSorter
Definition: IdentifierByDetElSorter.h:17
Muon::MMPrepData::setAuthor
void setAuthor(Author author)
Definition: MMPrepData.cxx:96
MuonStation.h
MmIdHelper::channelID
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channel) const
Definition: MmIdHelper.cxx:736
Trk::Surface::transform
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
IdContext
This class saves the "context" of an expanded identifier (ExpandedIdentifier) for compact or hash ver...
Definition: IdContext.h:26
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
IROBDataProviderSvc.h
merge
Definition: merge.py:1
generate::Zero
void Zero(TH1D *hin)
Definition: generate.cxx:32
Identifier
Definition: IdentifierFieldParser.cxx:14