17 void resize_all (
const std::size_t nEle,
const std::size_t
size,
auto&&... vecs) {
18 for (std::size_t idx = 0;
idx < nEle; ++
idx) {
22 double inDegrees(
double angle) {
23 return angle / Gaudi::Units::deg;
28 using namespace MuonR4;
29 using namespace MuonVal;
31 constexpr std::size_t
s_nStations {Acts::toUnderlying(StIndex::StIndexMax)};
32 using simHitSet = std::unordered_set<const xAOD::MuonSimHit*>;
37 if (!
hit)
return std::nullopt;
39 for (
const auto& [tp, truthHitSets] : truthHits) {
40 for (
const simHitSet& truthHitSet : truthHitSets) {
41 if (truthHitSet.count(
hit)) {
43 else return truthHits.size();
53 for (
const SpacePoint*
hit : pattern.hitsInStation(station)) {
54 if (
hit ==
sp)
return true;
64 m_tree.addBranch(std::make_unique<EventInfoBranch>(
m_tree, infoOpts));
111 return StatusCode::SUCCESS;
116 return StatusCode::SUCCESS;
144 ATH_MSG_DEBUG(
"Succesfully retrieved input collections: Global Patterns: "<<globPatterns->
size()
145 <<
", truth segments: "<<(readTruthSegments? std::to_string(readTruthSegments->
size()) : std::to_string(-1))
146 <<
", Rois: "<<(roiCollection ? std::to_string(roiCollection->
size()) : std::to_string(-1)));
159 std::vector<const MuonR4::SpacePointContainer*>{spContainer, NSWspContainer});
164 return StatusCode::SUCCESS;
174 if (tp->eta() < roi->etaMinus() || tp->eta() > roi->etaPlus())
continue;
178 if (dPhiPlus >= 0. && dPhiMinus <= 0.)
return true;
194 const std::vector<const MuonR4::SpacePointContainer*>& spContainers) {
195 if (!
m_isMC || truthHits.empty())
return;
199 using LayerBookeeper = std::unordered_map<const MuonGMR4::SpectrometerSector*, std::set<unsigned>>;
200 using MeasBookeeper = std::array<std::vector<const SpacePoint*>, Acts::toUnderlying(
nTypes)>;
202 MeasBookeeper measInStation{};
203 LayerBookeeper seenEtaLayers{};
204 LayerBookeeper seenPhiLayers{};
206 auto processMeas = [&truthHits, &measInStation, &seenEtaLayers, &seenPhiLayers,
this]
211 (
type ==
NonPrec && (isPrec || !
sp->measuresEta())) || (
type == Phi &&
sp->measuresEta())) {
215 std::vector<const SpacePoint*>& outCont {measInStation[Acts::toUnderlying(
type)]};
216 if (std::ranges::find_if(outCont, [
sp](
const SpacePoint* s) {
217 return s->primaryMeasurement() ==
sp->primaryMeasurement(); }) != outCont.end()) {
223 const bool isDoubleMatched {
sp->dimension() == 2u &&
sp->secondaryMeasurement() &&
isTruthMatched(*
sp->secondaryMeasurement(), truthHits) == tpIdx};
224 if (process2Dmeas && !isDoubleMatched)
return;
229 if (
sp->measuresEta()) {
230 const bool isSeenLayer {seenEtaLayers[
sp->msSector()].count(layNum) > 0};
231 if (isSeenLayer && !
sp->isStraw())
return;
232 if (!isSeenLayer) seenEtaLayers[
sp->msSector()].insert(layNum);
234 ++measCounter[tpIdx][stIdx];
237 if (
sp->measuresPhi() && isDoubleMatched) {
238 seenPhiLayers[
sp->msSector()].insert(layNum);
240 measInStation[Acts::toUnderlying(Phi)].push_back(
sp);
243 if (seenPhiLayers[
sp->msSector()].count(layNum) > 0)
return;
244 seenPhiLayers[
sp->msSector()].insert(layNum);
247 outCont.push_back(
sp);
248 ATH_MSG_VERBOSE(
"---> "<<(isPrec ?
"Prec" : (
type ==
NonPrec ?
"Trig" :
"Phi "))<<
" " << *
sp <<
" in sector "<<
sp->msSector()->identString() <<
" lay "<<layNum);
252 for (
const auto& [tp, _] : truthHits) {
257 m_gen_Q.push_back(tp->charge());
260 std::vector<int> sectors{};
262 const int side {tp->eta() > 0 ? 1 : -1};
265 ATH_MSG_VERBOSE(
"tp: " << tpIdx <<
", Eta: " << tp->eta() <<
", Phi: " << inDegrees(tp->phi()) <<
", Pt [GeV]: " << tp->pt() * 1e-3 <<
", Q: " << tp->charge());
266 for (std::size_t stIdx = 0; stIdx <
s_nStations; ++stIdx) {
269 for (
auto&
vec : measInStation)
vec.clear();
270 seenEtaLayers.clear();
271 seenPhiLayers.clear();
275 for (
const bool process2Dmeas : {
true,
false}) {
276 for (
const auto& spContainer : spContainers) {
277 if (!spContainer)
continue;
280 if (
static_cast<std::size_t
>(
m_idHelperSvc->stationIndex(bucket->front()->identify())) != stIdx)
continue;
282 if (bucket->msSector()->side() != side ||
283 std::ranges::none_of(sectors, [&](
int s){ return bucket->msSector()->sector() == s; })) {
286 for (
const auto&
sp : *bucket) {
288 processMeas(
sp.get(),
type, process2Dmeas, tpIdx, stIdx);
294 if (msgLevel(MSG::VERBOSE)) {
295 const auto gen_nNonPrecHits {
static_cast<unsigned>(
m_gen_nNonPrecMeas[tpIdx][stIdx])};
296 const auto gen_nPrecHits {
static_cast<unsigned>(
m_gen_nPrecMeas[tpIdx][stIdx])};
297 const auto gen_nPhiHits {
static_cast<unsigned>(
m_gen_nPhiMeas[tpIdx][stIdx])};
298 if (gen_nNonPrecHits + gen_nPrecHits + gen_nPhiHits > 0) {
300 << gen_nNonPrecHits <<
"/" << gen_nPrecHits <<
"/" << gen_nPhiHits);
327 for (
const auto&
sp : *bucket) {
331 if (
const auto tpIdx {
isTruthMatched(*
sp->primaryMeasurement(), truthHits)}; tpIdx.has_value()) {
333 spMatchedToTruthBranch[tpIdx.value()].
push_back(treeIdx);
337 std::size_t patternIdx{0};
339 for (
const StIndex station : pattern->getStations()) {
340 for (
const SpacePoint*
sp : pattern->hitsInStation(station)) {
342 spMatchedToPatternBranch[patternIdx].
push_back(treeIdx);
350 const std::vector<const MuonR4::SpacePointContainer*>& spContainers) {
362 auto isSecondaryMatched = [&truthHits](
const SpacePoint*
sp, std::size_t tpIdx) {
363 return sp->secondaryMeasurement() &&
isTruthMatched(*
sp->secondaryMeasurement(), truthHits) == tpIdx;
365 std::size_t patternIdx{0};
368 std::unordered_map<std::size_t, std::vector<const SpacePoint*>> patternTruthHits{};
370 const std::vector<StIndex> stations {pattern->getStations()};
371 for (
const StIndex station : stations) {
372 for (
const SpacePoint*
sp : pattern->hitsInStation(station)) {
376 if (
const auto tpIdx {
isTruthMatched(*
sp->primaryMeasurement(), truthHits)}; tpIdx.has_value()) {
378 if (*tpIdx >= truthHits.size() ) {
381 patternTruthHits[*tpIdx].push_back(
sp);
386 if (!patternTruthHits.empty()) {
388 std::vector<std::size_t> sortedTPs {};
389 std::ranges::transform(patternTruthHits, std::back_inserter(sortedTPs), [](
const auto&
pair){
return pair.first; });
390 std::ranges::sort(sortedTPs, [&patternTruthHits](
const auto&
a,
const auto& b){
391 return patternTruthHits.at(
a).size() > patternTruthHits.at(b).size();
393 const auto mainTP = sortedTPs.front();
399 for (
const auto& [tpIdx, hits] : patternTruthHits) {
400 if (tpIdx == mainTP)
continue;
407 std::ranges::transform(sortedTPs, std::back_inserter(
m_pat_MatchedToTruth[patternIdx]), [](
const std::size_t& tp){
return tp; });
411 if (!spContainer)
continue;
413 bool bucketInPattern{
false};
415 std::vector<const SpacePoint*> allHits{};
417 for (
const auto&
sp : *bucket) {
419 bucketInPattern =
true;
421 allHits.push_back(
sp.get());
423 if (bucketInPattern) {
430 m_pat_Eta.push_back(-std::log(std::tan(pattern->theta()/2.)));
435 m_pat_side.push_back(pattern->hitsInStation(stations.front()).front()->msSector()->side());
438 if (msgLevel(MSG::VERBOSE)) {
440 unsigned nPrecHits{0}, nNonPrecHits{0}, nPhiHits{0};
441 unsigned gen_nPrecHits{0}, gen_nNonPrecHits{0}, gen_nPhiHits{0};
442 for (std::size_t stIdx = 0; stIdx <
s_nStations; ++stIdx) {
446 if (mainTP < 0)
continue;
447 gen_nPrecHits +=
static_cast<unsigned>(
m_gen_nPrecMeas[mainTP][stIdx]);
449 gen_nPhiHits +=
static_cast<unsigned>(
m_gen_nPhiMeas[mainTP][stIdx]);
451 ATH_MSG_VERBOSE(
"Pat #" << patternIdx<<
": " << *pattern <<
"mainTP: "<<std::to_string(mainTP)
452 <<
", nTruthMatchedHits Trig: "<<nNonPrecHits<<
" / "<<gen_nNonPrecHits<<
", Prec: "<<nPrecHits<<
" / "<<gen_nPrecHits<<
", Phi: "<<nPhiHits<<
" / "<<gen_nPhiHits);
459 if (!fastMuons)
return;
469 assert(patItr != patternCont->
end());
470 const std::size_t patIdx = std::distance(patternCont->
begin(), patItr);
473 ATH_MSG_VERBOSE(
"FastMuonSA eta: "<<mu->eta()<<
", phi[Deg]: "<<inDegrees(mu->phi())
474 <<
", pt[GeV]: "<<mu->pt()/Gaudi::Units::GeV<<
", q: "<<mu->charge());
478 const std::size_t patIdx,
481 const bool isSecondaryMatched) {
484 const auto updateCounts = [&](
unsigned char& nonPrecCount,
485 unsigned char& precCount,
486 unsigned char& phiCount) {
487 if (
sp->measuresEta()) {
494 if (
sp->measuresPhi() && (!isTruthInfo || isSecondaryMatched)) {
501 const auto stIdx = Acts::toUnderlying(hitSt);
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_VERBOSE(x,...)
std::vector< size_t > vec
size_t size() const
Number of registered mappings.
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
bool empty() const noexcept
Returns true if the collection is empty.
Data class to represent an eta maximum in hough space.
: The muon space point bucket represents a collection of points that will bre processed together in t...
The muon space point is the combination of two uncalibrated measurements one of them measures the eta...
void fillTruthInfo(const TruthParticleMap &truthHits, const std::vector< const MuonR4::SpacePointContainer * > &spContainers)
Fill the truth particle information into the tree.
MuonVal::VectorBranch< float > & m_gen_Phi
MuonVal::MatrixBranch< unsigned char > & m_pat_nAllNonPrecMeas
Number of trigger eta measurements in the buckets crossed by the pattern, grouped by station.
MuonVal::VectorBranch< unsigned char > & m_spType
Type of spacepoints: 1 for trigger eta, 2 for precision, 3 for only-phi.
MuonVal::VectorBranch< float > & m_roi_ZMax
SG::ReadHandleKey< MuonR4::SpacePointContainer > m_NSWspKey
ActsTrk::GeoContextReadKey_t m_geoCtxKey
MuonVal::MatrixBranch< unsigned char > & m_pat_nNonPrecMeas
Number of trigger eta measurements per station.
measType
Enum for measurement types.
SG::ReadHandleKey< xAOD::MuonContainer > m_fastMuonKey
MuonVal::MatrixBranch< unsigned char > & m_pat_nAllPhiMeas
Number of phi measurements in the buckets crossed by the pattern, grouped by station.
MuonVal::MatrixBranch< unsigned char > & m_pat_nTruthPrecMeas
Number of truth precision measurements per station.
SG::ReadHandleKey< MuonR4::GlobalPatternContainer > m_patternKey
MuonVal::ScalarBranch< unsigned > & m_pat_n
====== Global Pattern block ===========
MuonVal::MatrixBranch< unsigned char > & m_spMatchedToPattern
Branch indicating which space points in the tree are associated to the i-th pattern.
BooleanProperty m_isSeededReco
MuonVal::VectorBranch< unsigned char > & m_muon_MatchedToPattern
MuonVal::MatrixBranch< unsigned char > & m_pat_nMisTruthPhiMeas
Number of mismatched truth phi measurements per station.
MuonVal::VectorBranch< unsigned char > & m_pat_nStations
Number of stations.
MuonVal::MatrixBranch< unsigned char > & m_NSWspMatchedToTruth
MuonVal::MatrixBranch< unsigned char > & m_pat_nPileupPhiMeas
Number of pileup phi measurements per station.
void fillRoIInfo(const TrigRoiDescriptorCollection *roiCollection)
Fill the RoI information into the tree.
MuonVal::VectorBranch< uint16_t > & m_pat_sector2
MuonVal::VectorBranch< float > & m_gen_Eta
MuonVal::MatrixBranch< unsigned char > & m_pat_nAllPrecMeas
Number of precision measurements in the buckets crossed by the pattern, grouped by station.
MuonVal::MatrixBranch< unsigned char > & m_pat_nPileupPrecMeas
Number of pileup precision measurements per station.
MuonVal::VectorBranch< float > & m_muon_Pt
MuonVal::VectorBranch< float > & m_pat_phi
MuonVal::VectorBranch< short > & m_muon_Q
SG::ReadHandleKey< TrigRoiDescriptorCollection > m_roiCollectionKey
std::map< const xAOD::TruthParticle *, std::vector< simHitSet > > TruthParticleMap
MuonVal::VectorBranch< short > & m_gen_Q
====== Truth particle block ===========
virtual StatusCode finalize() override
MuonVal::MatrixBranch< unsigned char > & m_gen_nPrecMeas
Number of precision measurements per station.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
void updatePatHitInfo(const ePatBranchType type, const std::size_t patIdx, const Muon::MuonStationIndex::StIndex hitSt, const MuonR4::SpacePoint *sp, const bool isSecondaryMatched=false)
Update the hit counts for a given pattern branch type.
ePatBranchType
Enum for different types of pattern hit content branches.
SG::ReadHandleKey< xAOD::MuonSegmentContainer > m_truthSegmentKey
MuonVal::VectorBranch< float > & m_roi_EtaMin
====== RoI info ===========
MuonVal::MatrixBranch< unsigned char > & m_pat_nTruthPhiMeas
Number of truth phi measurements per station.
void fillFastRecoMuonInfo(const xAOD::MuonContainer *muonCont, const MuonR4::GlobalPatternContainer *patternCont)
Fill the info associated to fast reco muons.
std::shared_ptr< SpacePointTesterModule > m_NSWspTester
MuonVal::VectorBranch< float > & m_roi_PhiMin
MuonVal::VectorBranch< float > & m_roi_PhiMax
std::shared_ptr< SpacePointTesterModule > m_spTester
====== Spacepoint block ===========
MuonVal::MatrixBranch< unsigned char > & m_pat_nTruthNonPrecMeas
Number of truth trigger eta measurements per station.
virtual StatusCode initialize() override
MuonVal::MatrixBranch< unsigned char > & m_pat_nPhiMeas
Number of phi measurements per station.
MuonVal::MatrixBranch< unsigned char > & m_pat_nPrecMeas
Number of precision measurements per station.
MuonVal::VectorBranch< float > & m_muon_Phi
MuonVal::VectorBranch< float > & m_roi_EtaMax
MuonVal::VectorBranch< float > & m_pat_meanNormResidual2
mean square normalized pattern residual
virtual StatusCode execute(const EventContext &ctx) override
Execute method.
BooleanProperty m_writeSpacePoints
MuonVal::VectorBranch< float > & m_gen_Pt
void fillSpacePointInfo(const MuonR4::SpacePointContainer *spc, const MuonR4::GlobalPatternContainer *patternCont, const TruthParticleMap &truthHits, SpacePointTesterModule &spTester, MuonVal::VectorBranch< unsigned char > &spTypeBranch, MuonVal::MatrixBranch< unsigned char > &spMatchedToPatternBranch, MuonVal::MatrixBranch< unsigned char > &spMatchedToTruthBranch) const
Fill the space point information into the tree.
MuonVal::MatrixBranch< unsigned char > & m_pat_nMisTruthNonPrecMeas
Number of mismatched truth trigger eta measurements per station.
MuonVal::VectorBranch< unsigned char > & m_NSWspType
void fillGlobPatternInfo(const MuonR4::GlobalPatternContainer *patternCont, const TruthParticleMap &truthHits, const std::vector< const MuonR4::SpacePointContainer * > &spContainers)
Fill the info associated to the global patterns into the tree.
MuonVal::VectorBranch< uint16_t > & m_pat_sector1
pattern primary & secondary sectors (different if the pattern is in the sector overlap)
MuonVal::MatrixBranch< unsigned char > & m_NSWspMatchedToPattern
MuonVal::MatrixBranch< unsigned char > & m_pat_nMisTruthPrecMeas
Number of mismatched truth precision measurements per station.
MuonVal::MuonTesterTree m_tree
MuonVal::VectorBranch< float > & m_muon_Eta
====== Fast Reco Muon info ===========
MuonVal::VectorBranch< short > & m_pat_side
+1 for A-, -1 of C-side
MuonVal::MatrixBranch< unsigned char > & m_pat_MatchedToTruth
Branch indicating which truth particles in the tree are associated to the i-th pattern.
MuonR4::SpacePointPerLayerSorter m_spSorter
MuonVal::MatrixBranch< unsigned char > & m_spMatchedToTruth
Branch indicating which space points in the tree are associated to the i-th truth particle.
MuonVal::MatrixBranch< unsigned char > & m_gen_nPhiMeas
Number of phi measurements per station.
MuonVal::MatrixBranch< unsigned char > & m_pat_nPileupNonPrecMeas
Number of pileup trigger eta measurements per station.
MuonVal::VectorBranch< float > & m_pat_Eta
pattern average theta & phi
MuonVal::MatrixBranch< unsigned char > & m_gen_nNonPrecMeas
Number of trigger eta measurements per station.
SG::ReadHandleKey< MuonR4::SpacePointContainer > m_spKey
TruthParticleMap fillTruthMap(const xAOD::MuonSegmentContainer *truthSegments, const TrigRoiDescriptorCollection *roiCollection) const
Fill the truth particle map.
MuonVal::VectorBranch< float > & m_roi_ZMin
unsigned int push_back(const MuonR4::SpacePointBucket &bucket)
@ isMC
Flag determining whether the branch is simulation.
void push_back(size_t i, const T &value)
void push_back(const T &value)
Adds a new element at the end of the vector.
void getSectors(double phi, std::vector< int > §ors) const
returns the main sector plus neighboring if the phi position is in an overlap region
nope - should be used for standalone also, perhaps need to protect the class def bits ifndef XAOD_ANA...
constexpr T deltaPhi(T phiA, T phiB)
Return difference phiA - phiB in range [-pi, pi].
const GlobalPattern * getParentPattern(const xAOD::MuonSegment &segment)
Retrieve the parent global pattern of the segment.
const xAOD::TruthParticle * getTruthMatchedParticle(const xAOD::MuonSegment &segment)
Returns the particle truth-matched to the segment.
std::unordered_set< const xAOD::MuonSimHit * > getMatchingSimHits(const xAOD::MuonSegment &segment)
: Returns all sim hits matched to a xAOD::MuonSegment
const xAOD::MuonSimHit * getTruthMatchedHit(const xAOD::MuonMeasurement &prdHit)
Returns the MuonSimHit, if there's any, matched to the uncalibrated muon measurement.
DataVector< GlobalPattern > GlobalPatternContainer
Abrivation of the GlobalPattern container type.
bool isPrecisionHit(const SpacePoint &hit)
Returns whether the uncalibrated spacepoint is a precision hit (Mdt, micromegas, stgc strips).
DataVector< SpacePointBucket > SpacePointContainer
Abrivation of the space point container type.
Lightweight algorithm to read xAOD MDT sim hits and (fast-digitised) drift circles from SG and fill a...
std::unordered_set< const xAOD::MuonSimHit * > simHitSet
bool isInPattern(const SpacePoint *sp, const StIndex station, const GlobalPattern &pattern)
std::map< const xAOD::TruthParticle *, std::vector< simHitSet > > TruthParticleMap
constexpr std::size_t s_nStations
std::optional< std::size_t > isTruthMatched(const xAOD::MuonMeasurement &meas, const TruthParticleMap &truthHits)
StIndex
enum to classify the different station layers in the muon spectrometer
const std::string & stName(StIndex index)
convert StIndex into a string
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
MuonSegmentContainer_v1 MuonSegmentContainer
Definition of the current "MuonSegment container version".
MuonMeasurement_v1 MuonMeasurement
MuonSimHit_v1 MuonSimHit
Defined the version of the MuonSimHit.
TruthParticle_v1 TruthParticle
Typedef to implementation.
Muon_v1 Muon
Reference the current persistent version:
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".
MuonSegment_v1 MuonSegment
Reference the current persistent version:
Helper for azimuthal angle calculations.