6 #include "GaudiKernel/SystemOfUnits.h"
15 #include "Acts/Utilities/Enumerate.hpp"
16 #include "GaudiKernel/PhysicalConstants.h"
30 using simHitSet = std::unordered_set<const xAOD::MuonSimHit*>;
48 template <
class SpType>
61 m_tree.addBranch(std::make_unique<EventInfoBranch>(m_tree, infoOpts));
63 ATH_CHECK(m_truthSegmentKey.initialize(!m_truthSegmentKey.empty()));
66 ATH_CHECK(m_inHoughSegmentSeedKeys.initialize());
67 ATH_CHECK(m_spKey.initialize(m_writeSpacePoints));
68 if (m_writeSpacePoints) {
69 m_spTester = std::make_unique<SpacePointTesterModule>(m_tree, m_spKey.key(), msgLevel());
70 m_tree.addBranch(m_spTester);
72 m_tree.disableBranch(m_spMatchedToPattern.name());
73 m_tree.disableBranch(m_spMatchedToSegment.name());
79 ATH_CHECK(m_visionTool.retrieve(EnableTool{!m_visionTool.empty()}));
81 return StatusCode::SUCCESS;
93 for (
unsigned int s = 0 ;
s < truthSigns.size(); ++
s) {
94 same += (truthSigns[
s] != 0) && truthSigns[
s] == recoSigns[
s];
98 std::vector<ObjectMatching>
103 std::vector<ObjectMatching> allAssociations{};
104 std::unordered_set<const SegmentSeed*> usedSeeds{};
105 std::unordered_set<const Segment*> usedSegs{};
111 std::vector<simHitSet> truthHitsVec{}, seedSimHitVec{}, segmentSimHitVec{};
123 ObjectMatching & matchedWithTruth = allAssociations.emplace_back();
125 matchedWithTruth.
chamber = m_detMgr->getSectorEnvelope((*truthHits.begin())->identify());
127 std::vector<std::pair<const SegmentSeed*, unsigned>> matchedSeeds{};
134 if (seed->msSector() != matchedWithTruth.
chamber) {
137 const simHitSet& seedHits{seedSimHitVec[seedIdx]};
138 unsigned int matchedHits =
countMatched(truthHits, seedHits);
142 matchedSeeds.emplace_back(std::make_pair(seed, matchedHits));
145 std::vector<std::pair<const Segment*, unsigned>> matchedSegs{};
152 const simHitSet& segmentHits{segmentSimHitVec[segmentIdx]};
153 unsigned int matchedHits =
countMatched(truthHits, segmentHits);
157 matchedSegs.emplace_back(std::make_pair(
segment,matchedHits));
163 std::ranges::sort(matchedSegs,
164 [
this, &truth, &gctx](
const std::pair<const Segment*, unsigned>& segA,
165 const std::pair<const Segment*, unsigned>& segB){
166 if (segA.second != segB.second)
return segA.second > segB.second;
167 return countOnSameSide(gctx, *truth, *segA.first) > countOnSameSide(gctx, *truth, *segB.first);
170 std::ranges::sort(matchedSeeds, [](
const std::pair<const SegmentSeed*, unsigned>& seedA,
171 const std::pair<const SegmentSeed*, unsigned>& seedB) {
172 return seedA.second > seedB.second;
179 for (
const auto& [
matched, nMatchedHits] : matchedSegs) {
183 usedSeeds.insert(
matched->parent());
188 for (
const auto& [seed , nHits] : matchedSeeds) {
193 usedSeeds.insert(seed);
203 for (
const Segment* seg: *segmentContainer) {
205 if (usedSegs.count(seg)) {
209 match.chamber = seg->msSector();
210 match.matchedSegments = {seg};
211 match.matchedSeeds = {seg->parent()};
213 usedSeeds.insert(seg->parent());
217 if (usedSeeds.count(seed)) {
221 match.chamber = seed->msSector();
222 match.matchedSeeds = {seed};
224 return allAssociations;
229 return StatusCode::SUCCESS;
233 const EventContext & ctx = Gaudi::Hive::currentContext();
245 segmentSeeds.insert(segmentSeeds.end(),readSegmentSeeds->begin(), readSegmentSeeds->end());
250 segments.insert(segments.end(),readSegments->begin(), readSegments->end());
255 ATH_MSG_DEBUG(
"Succesfully retrieved input collections. Seeds: "<<segmentSeeds.size()
256 <<
", segments: "<<segments.size() <<
", truth segments: "<<(readTruthSegments? readTruthSegments->size() : -1)<<
".");
257 std::vector<ObjectMatching>
objects = matchWithTruth(gctx, readTruthSegments, segmentSeeds.asDataVector(),
258 segments.asDataVector());
260 fillChamberInfo(
obj.chamber);
261 fillTruthInfo(gctx,
obj.truthSegment);
263 fillSegmentInfo(gctx,
obj);
266 return StatusCode::SUCCESS;
270 m_out_stationSide = msSector->
side();
276 m_out_hasTruth =
true;
282 m_out_gen_Eta = segDir.eta();
283 m_out_gen_Phi = segDir.phi();
284 m_out_gen_Pt = acc_pt(*
segment);
285 m_out_gen_Q = acc_charge(*
segment);
297 m_out_gen_y0 = chamberPos.y();
298 m_out_gen_x0 = chamberPos.x();
299 m_out_gen_time =
segment->t0();
309 const Amg::Vector3D chamberPos = localToChamber * xAOD::toEigen(hit->localPosition());
310 minYhit =
std::min(chamberPos.y(), minYhit);
311 maxYhit =
std::max(chamberPos.y(), maxYhit);
313 m_out_gen_minYhit = minYhit;
314 m_out_gen_maxYhit = maxYhit;
316 ATH_MSG_DEBUG(
"A true max on chamber index "<<m_out_chamberIndex.getVariable()<<
" side "<<m_out_stationSide.getVariable()<<
" phi "<<m_out_stationPhi.getVariable()<<
" with "
317 <<m_out_gen_nMDTHits.getVariable()<<
" MDT and "<<m_out_gen_nRPCHits.getVariable()+m_out_gen_nTGCHits.getVariable()<<
" trigger hits is at "
318 <<m_out_gen_tantheta.getVariable()<<
" and "<<m_out_gen_y0.getVariable());
323 m_out_nSpacePoints = bucket.size();
324 m_out_nPrecSpacePoints = std::ranges::count_if(bucket, [](
const SpacePointBucket::value_type& sp){
327 m_out_nPhiSpacePoints = std::ranges::count_if(bucket, [](
const SpacePointBucket::value_type& sp){
328 return sp->measuresPhi();
330 if (!m_visionTool.isEnabled()){
333 m_out_nTrueSpacePoints = std::ranges::count_if(bucket,[
this](
const SpacePointBucket::value_type& sp){
334 return m_visionTool->isLabeled(*sp);
336 m_out_nTruePrecSpacePoints = std::ranges::count_if(bucket,[
this](
const SpacePointBucket::value_type& sp){
337 return isPrecHit(*sp) && m_visionTool->isLabeled(*sp);
339 m_out_nTruePhiSpacePoints = std::ranges::count_if(bucket,[
this](
const SpacePointBucket::value_type& sp){
340 return sp->measuresPhi() && m_visionTool->isLabeled(*sp);
345 m_out_seed_n =
obj.matchedSeeds.size();
346 for (
const auto [iseed, seed] : Acts::enumerate(
obj.matchedSeeds)){
348 fillBucketInfo(*seed->parentBucket());
350 double minYhit = m_out_bucketEnd.getVariable();
351 double maxYhit = m_out_bucketStart.getVariable();
352 for (
const SpacePoint* hit : seed->getHitsInMax()){
353 minYhit =
std::min(hit->positionInChamber().y(),minYhit);
354 maxYhit =
std::max(hit->positionInChamber().y(),maxYhit);
356 m_out_seed_minYhit.push_back(minYhit);
357 m_out_seed_maxYhit.push_back(maxYhit);
359 m_out_seed_hasPhiExtension.push_back(seed->hasPhiExtension());
360 m_out_seed_nMatchedHits.push_back(
countMatched(
obj.truthSegment, seed));
361 m_out_seed_y0.push_back(seed->interceptY());
362 m_out_seed_tantheta.push_back(seed->tanTheta());
363 if (seed->hasPhiExtension()){
364 m_out_seed_x0.push_back(seed->interceptX());
365 m_out_seed_tanphi.push_back(seed->tanPhi());
367 m_out_seed_x0.push_back(-999);
368 m_out_seed_tanphi.push_back(-999);
371 m_out_seed_nHits.push_back(seed->getHitsInMax().size());
372 unsigned nMdtSeed{0}, nRpcSeed{0}, nTgcSeed{0}, nMmSeed{0}, nsTgcSeed{0};
373 unsigned nPrecHits{0}, nEtaHits{0}, nPhiHits{0}, nTrueHits{0}, nTruePrecHits{0}, nTrueEtaHits{0}, nTruePhiHits{0};
374 std::vector<unsigned char>
matched{};
375 for (
const HoughHitType & houghSP: seed->getHitsInMax()){
376 if (m_writeSpacePoints){
377 unsigned treeIdx = m_spTester->push_back(*houghSP);
378 if (treeIdx >=
matched.size()){
384 nPhiHits += houghSP->measuresPhi();
385 nEtaHits += houghSP->measuresEta();
387 if (m_visionTool.isEnabled()) {
388 nTrueHits += m_visionTool->isLabeled(*houghSP);
389 nTruePrecHits += m_visionTool->isLabeled(*houghSP) &&
isPrecHit(*houghSP);
390 nTruePhiHits += m_visionTool->isLabeled(*houghSP) && houghSP->measuresPhi();
391 nTrueEtaHits += m_visionTool->isLabeled(*houghSP) && houghSP->measuresEta();
393 switch (houghSP->type()) {
398 nRpcSeed+=houghSP->measuresEta();
399 nRpcSeed+=houghSP->measuresPhi();
402 nTgcSeed+=houghSP->measuresEta();
403 nTgcSeed+=houghSP->measuresPhi();
406 nsTgcSeed += houghSP->measuresEta();
407 nsTgcSeed += houghSP->measuresPhi();
413 ATH_MSG_WARNING(
"Technology "<<houghSP->identify() <<
" not yet implemented");
416 m_out_seed_nMdt.push_back(nMdtSeed);
417 m_out_seed_nRpc.push_back(nRpcSeed);
418 m_out_seed_nTgc.push_back(nTgcSeed);
419 m_out_seed_nsTgc.push_back(nsTgcSeed);
420 m_out_seed_nMm.push_back(nMmSeed);
422 m_out_seed_nPrecHits.push_back(nPrecHits);
423 m_out_seed_nEtaHits.push_back(nEtaHits);
424 m_out_seed_nPhiHits.push_back(nPhiHits);
426 m_out_seed_nTrueHits.push_back(nTrueHits);
427 m_out_seed_nTruePrecHits.push_back(nTruePrecHits);
428 m_out_seed_nTrueEtaHits.push_back(nTrueEtaHits);
429 m_out_seed_nTruePhiHits.push_back(nTruePhiHits);
431 m_out_seed_ledToSegment.push_back(
obj.matchedSeedFoundSegment.at(iseed));
432 if (m_writeSpacePoints) {
433 m_spMatchedToPattern[iseed] = std::move(
matched);
440 using namespace SegmentFit;
442 m_out_segment_n =
obj.matchedSegments.size();
444 m_out_segment_hasPhi.push_back(std::ranges::find_if(
segment->measurements(), [](
const auto& meas){ return meas->measuresPhi();})
445 !=
segment->measurements().end());
446 m_out_segment_fitIter.push_back(
segment->nFitIterations());
448 m_out_segment_chi2.push_back(
segment->chi2());
449 m_out_segment_nDoF.push_back(
segment->nDoF());
450 m_out_segment_hasTimeFit.push_back(
segment->hasTimeFit());
460 m_out_segment_y0.push_back(locPos.y());
461 m_out_segment_x0.push_back(locPos.x());
462 m_out_segment_time.push_back(
segment->segementT0() +
segment->position().mag() * c_inv);
464 unsigned nMdtHits{0}, nRpcEtaHits{0}, nRpcPhiHits{0}, nTgcEtaHits{0}, nTgcPhiHits{0},
465 nMmEtaHits{0}, nMmStereoHits{0}, nStgcStripHits{0},nStgcWireHits{0}, nStgcPadHits{0};
466 unsigned nTrueHits{0}, nTruePrecHits{0}, nTrueEtaHits{0}, nTruePhiHits{0};
471 std::vector<unsigned char>
matched;
472 for (
const auto & meas :
segment->measurements()){
475 minYhit =
std::min(meas->positionInChamber().y(),minYhit);
476 maxYhit =
std::max(meas->positionInChamber().y(),maxYhit);
477 if (m_writeSpacePoints) {
478 unsigned treeIdx = m_spTester->push_back(*meas->spacePoint());
479 if (treeIdx >=
matched.size()){
484 if (m_visionTool.isEnabled()) {
485 nTrueHits += m_visionTool->isLabeled(*meas->spacePoint());
486 nTruePrecHits +=
isPrecHit(*meas) && m_visionTool->isLabeled(*meas->spacePoint());
487 nTrueEtaHits += meas->measuresEta() && m_visionTool->isLabeled(*meas->spacePoint());
488 nTruePhiHits += meas->measuresPhi() && m_visionTool->isLabeled(*meas->spacePoint());
490 switch (meas->type()) {
495 nRpcEtaHits += meas->measuresEta();
496 nRpcPhiHits += meas->measuresPhi();
499 nTgcEtaHits += meas->measuresEta();
500 nTgcPhiHits += meas->measuresPhi();
503 const MmIdHelper& idHelper{m_idHelperSvc->mmIdHelper()};
504 nMmEtaHits += !idHelper.
isStereo(meas->spacePoint()->identify());
505 nMmStereoHits += !idHelper.isStereo(meas->spacePoint()->identify());
508 const auto* prd =
static_cast<const xAOD::sTgcMeasurement*
>(meas->spacePoint()->primaryMeasurement());
509 nStgcStripHits += prd->
channelType() == sTgcIdHelper::sTgcChannelTypes::Strip;
510 nStgcWireHits += prd->channelType() == sTgcIdHelper::sTgcChannelTypes::Wire;
511 nStgcPadHits += prd->channelType() == sTgcIdHelper::sTgcChannelTypes::Pad;
514 nStgcWireHits += prd->
channelType() == sTgcIdHelper::sTgcChannelTypes::Wire;
515 nStgcPadHits += prd->channelType() == sTgcIdHelper::sTgcChannelTypes::Pad;
522 m_out_segment_nMdtHits.push_back(nMdtHits);
523 m_out_segment_nRpcEtaHits.push_back(nRpcEtaHits);
524 m_out_segment_nRpcPhiHits.push_back(nRpcPhiHits);
525 m_out_segment_nTgcEtaHits.push_back(nTgcEtaHits);
526 m_out_segment_nTgcPhiHits.push_back(nTgcPhiHits);
528 m_out_segment_nMmEtaHits.push_back(nMmEtaHits);
529 m_out_segment_nMmStereoHits.push_back(nMmStereoHits);
530 m_out_segment_nsTgcStripHits.push_back(nStgcStripHits);
531 m_out_segment_nsTgcWireHits.push_back(nStgcWireHits);
532 m_out_segment_nsTgcPadpHits.push_back(nStgcPadHits);
535 m_out_segment_nTrueHits.push_back(nTrueHits);
536 m_out_segment_nTruePrecHits.push_back(nTruePrecHits);
537 m_out_segment_nTruePhiHits.push_back(nTruePhiHits);
538 m_out_segment_nTrueEtaHits.push_back(nTrueEtaHits);
540 m_out_segment_minYhit.push_back(minYhit);
541 m_out_segment_maxYhit.push_back(maxYhit);
542 if (m_writeSpacePoints) {
543 m_spMatchedToSegment.push_back(std::move(
matched));