10#include "HepPDT/ParticleDataTable.hh"
19 template <
typename T, std::
size_t N>
20 void accumulateTo(
typename std::vector<std::array<T,N> >
::const_iterator src_begin,
22 std::array<T,N> &dest) {
23 for (
typename std::vector<std::array<T,N> >
::const_iterator src_iter = src_begin;
26 for (
unsigned int elm_i=0; elm_i<
dest.size(); ++elm_i) {
27 assert( elm_i < src_iter->
size() );
28 dest[elm_i] += (*src_iter)[elm_i];
33 template <
typename T,
bool LastRowOnly=false>
34 void accumulateToLastColumnRow(std::size_t n_rows, std::size_t n_cols, std::vector<T> &stat) {
37 auto stat_begin_iter =
stat.begin();
39 auto stat_total_row_begin_iter =
stat.begin() + (n_rows-1) * n_cols;
40 assert(
static_cast<std::size_t
>(stat_total_row_begin_iter - stat_begin_iter) <
stat.size());
42 for (std::size_t row_i = 0; row_i < n_rows-1; ++row_i) {
43 auto stat_end_iter = stat_begin_iter + n_cols - 1 ;
44 assert(
static_cast<std::size_t
>(stat_end_iter -
stat.begin()) <
stat.size());
45 auto stat_total_row_iter = stat_total_row_begin_iter;
46 if constexpr(!LastRowOnly) {
47 accumulateTo(stat_begin_iter, stat_end_iter, *stat_end_iter );
51 for (; stat_begin_iter != stat_end_iter; ++stat_begin_iter, ++stat_total_row_iter) {
52 assert(
static_cast<std::size_t
>(stat_begin_iter -
stat.begin()) <
stat.size());
53 assert(
static_cast<std::size_t
>(stat_total_row_iter - stat.begin()) < stat.size());
54 for (
unsigned int idx=0; idx < stat_total_row_iter->size(); ++idx) {
55 stat_total_row_iter->at(idx) += stat_begin_iter->at(idx);
60 else if constexpr(!LastRowOnly) {
61 auto stat_end_iter = stat_begin_iter + n_cols - 1 ;
62 accumulateTo(stat_begin_iter, stat_end_iter, *stat_end_iter );
67 void accumulateToLastRow(std::size_t n_rows, std::size_t n_cols, std::vector<T> &stat) {
68 accumulateToLastColumnRow<T,true>(n_rows, n_cols, stat);
71 template <
typename T, std::
size_t N>
72 void addStat(
const std::vector<std::array<T,N> > &src, std::vector<std::array<T,N> > &dest) {
73 assert(
src.size() ==
dest.size());
75 for (
const std::array<T,N> &src_elm : src) {
76 assert( idx <
dest.size());
77 std::array<T,N> &dest_elm =
dest[
idx];
79 for (
const T &val : src_elm) {
80 assert( val_i < dest_elm.size());
88 inline double sqr(
double a) {
return a*
a; }
90 inline std::array<float, 2>
computeRatio(
unsigned int numerator_counts,
unsigned int denominator_counts) {
91 double inv_denominator_counts = denominator_counts > 0 ? 1./denominator_counts : 0.;
92 return std::array<float, 2> {
93 static_cast<float>(numerator_counts * inv_denominator_counts),
94 static_cast<float>(sqrt( numerator_counts * (denominator_counts-numerator_counts)
95 * inv_denominator_counts *
sqr(inv_denominator_counts) ))
99 std::string hfill(
const std::string &
head,
const std::string &
tail, std::size_t
width) {
101 std::stringstream
out;
108 std::stringstream
out;
109 for (uint8_t val : counts) {
110 out <<
" " << std::setw(2) <<
static_cast<int>(
val);
118 inline MsgStream &
operator<<(MsgStream &out,
const ActsUtils::Stat &stat) {
124 ISvcLocator *pSvcLocator)
137 template <
bool IsDebug>
138 template <
class T_OutStream>
140 if constexpr(IsDebug) {
141 out <<
"Weighted measurement sum per truth particle without associated counts :" << m_measPerTruthParticleWithoutCounts << std::endl
142 << m_measPerTruthParticleWithoutCounts.histogramToString() << std::endl
143 <<
"Match probability of best match :" << m_bestMatchProb << std::endl
144 << m_bestMatchProb.histogramToString() << std::endl
145 <<
"Match probability of next-to-best match :" << m_nextToBestMatchProb << std::endl
146 << m_nextToBestMatchProb.histogramToString() << std::endl;
150 template <
bool IsDebug>
152 if constexpr(IsDebug) {
153 std::lock_guard<std::mutex>
lock(m_mutex);
154 m_measPerTruthParticleWithoutCounts.add(weighted_measurement_sum);
157 template <
bool IsDebug>
159 if constexpr(IsDebug) {
160 std::lock_guard<std::mutex>
lock(m_mutex);
161 m_bestMatchProb.add(best_match_prob[0]);
162 m_nextToBestMatchProb.add(best_match_prob[1]);
173 msg(MSG::INFO) <<
"Truth selection cuts: " << std::endl;
174 unsigned int cut_i=0;
175 std::size_t total = std::accumulate ( m_detailedStat.m_truthSelectionCuts.m_histogram.begin(),
176 m_detailedStat.m_truthSelectionCuts.m_histogram.end(), 0u);
177 msg() << std::setw(3) <<
"" <<
" " << std::setw(20) << total <<
" total" << std::endl;
178 if (m_detailedStat.m_truthSelectionCuts.m_histogram.at(cut_i) > 0) {
179 msg() << std::setw(3) <<
"" <<
" "
180 << std::setw(20) << (total - m_detailedStat.m_truthSelectionCuts.m_histogram.at(cut_i))
181 <<
" underflow" << std::endl;
183 total -= m_detailedStat.m_truthSelectionCuts.m_histogram.at(cut_i++);
185 total -= m_detailedStat.m_truthSelectionCuts.m_histogram.at(cut_i);
186 msg() << std::setw(3) << cut_i <<
" " << std::setw(20) << total <<
" " << name << std::endl;
189 total -= m_detailedStat.m_truthSelectionCuts.m_histogram.at(cut_i);
191 msg() << std::setw(3) <<
"" <<
" " << std::setw(20) << total <<
" overflow" << std::endl;
194 msg() << m_detailedStat.m_truthSelectionCuts.histogramToString();
199 return StatusCode::SUCCESS;
208 std::array<unsigned int,2> best_match_i{std::numeric_limits<unsigned int>::max(),std::numeric_limits<unsigned int>::max()};
209 std::array<float,2> best_match_prob {};
211 std::array<unsigned int,2> best_match_i_nonoise{std::numeric_limits<unsigned int>::max(),std::numeric_limits<unsigned int>::max()};
212 std::array<float,2> best_match_prob_nonoise{};
220 double total_sum_for_prob_nonoise=total_sum_for_prob;
221 total_sum_for_prob += noise_sum;
223 if (total_sum_for_prob>0.) {
227 unsigned int truth_i=0;
229 for (
const std::pair<const xAOD::TruthParticle *, HitCounterArray > &
233 float match_prob_nonoise = truth_sum_for_prob /total_sum_for_prob_nonoise;
234 float match_prob = truth_sum_for_prob /total_sum_for_prob;
235 if (match_prob>1 || match_prob<0.) {
236 ATH_MSG_ERROR(
"Negative or too large truth match \"probability\". This should not happen."
237 <<
" Track hits: " << dumpCounts(total_counts)
238 <<
" noise hits of those: " << dumpCounts(noise_counts)
239 <<
" truth hits: " << dumpCounts(hit_counts_for_associated_truth_particle.second));
241 if (match_prob>best_match_prob[1]) {
242 int dest_i=match_prob<best_match_prob[0];
243 best_match_i[1]=best_match_i[0];
244 best_match_prob[1]=best_match_prob[0];
245 best_match_prob[dest_i]=match_prob;
246 best_match_i[dest_i]=truth_i;
248 if (match_prob_nonoise>best_match_prob_nonoise[1]) {
249 int dest_i=match_prob_nonoise<best_match_prob_nonoise[0];
250 best_match_i_nonoise[1]=best_match_i_nonoise[0];
251 best_match_prob_nonoise[1]=best_match_prob_nonoise[0];
252 best_match_prob_nonoise[dest_i]=match_prob_nonoise;
253 best_match_i_nonoise[dest_i]=truth_i;
259 if (best_match_i_nonoise[0] != best_match_i[0]) {
274 float hit_efficiency = 0.;
275 std::unordered_map<const xAOD::TruthParticle *,HitCounterArray>::const_iterator
276 best_truth_particle_counts_iter = truth_particle_hit_counts.find( best_match );
278 if (best_truth_particle_counts_iter != truth_particle_hit_counts.end()) {
281 hit_efficiency = truth_sum > 0u ? (common_truth_sum/truth_sum) : 0.;
293 float hit_purity = common_truth_sum / total_sum;
299 float best_match_pt = best_match->
pt();
302 event_stat.
fill( eta_category_i, pdg_id_category_i, hit_efficiency, hit_purity, best_match_prob[0], best_match );
317 <<
". This should not happen." );
326 std::size_t n_tracks,
331 for(
const std::pair<const xAOD::TruthParticle * const,ActsTrk::HitCounterArray> &truth_particle : truth_particle_hit_counts) {
336 float truth_particle_pt = truth_particle.first->pt();
337 std::size_t eta_category_i =
getPtEtaStatCategory(truth_particle_pt, truth_particle.first->eta());
338 std::size_t pdg_id_category_i =
getPtPdgIdStatCategory(truth_particle_pt, truth_particle.first->pdg_id());
348 std::lock_guard<std::mutex>
lock(m_statMutex);
357 m_detailedStat += event_stat;
364 std::vector<float>::const_iterator pt_bin_iter = std::upper_bound(
m_statPtBins.begin(),
367 std::vector<float>::const_iterator eta_bin_iter = std::upper_bound(
m_statEtaBins.begin(),
371 +
static_cast<std::size_t
>(eta_bin_iter -
m_statEtaBins.begin());
374 std::vector<float>::const_iterator pt_bin_iter = std::upper_bound(
m_statPtBins.begin(),
377 int abs_pdg_id = std::min(std::abs(pdg_id),
s_pdgIdMax);
378 std::vector< int >::const_iterator iter = std::find(m_pdgId.begin(), m_pdgId.end(), abs_pdg_id);
379 if (iter == m_pdgId.end()){
380 if (m_pdgId.size() < m_pdgId.capacity()) {
381 std::lock_guard<std::mutex>
lock(m_statMutex);
383 iter = std::find(m_pdgId.begin(), m_pdgId.end(), abs_pdg_id);
384 if (iter == m_pdgId.end()){
385 m_pdgId.push_back(abs_pdg_id);
386 iter = m_pdgId.end()-1;
390 iter=m_pdgId.begin();
393 return (m_pdgId.capacity()) *
static_cast<std::size_t
>(pt_bin_iter -
m_statPtBins.begin())
394 + (iter - m_pdgId.begin());
398 if (!bin_edges.empty())
400 float last_eta = bin_edges[0];
401 for (
float eta : bin_edges)
405 ATH_MSG_FATAL(bin_label +
" bins for statistics counter not in ascending order.");
428 m_pdgId.reserve(max_pdg_id_slots);
429 m_pdgId.push_back(1000000000);
432 template <
bool DetailEnabled>
435 if constexpr(DetailEnabled) {
445 template <
bool DetailEnabled>
447 const std::vector<float> &statPtBins,
448 const std::vector<float> &statEtaBins,
449 std::vector< int > &pdgId,
451 bool pdgIdCategorisation,
452 bool useAbsEtaForStat) {
453 if constexpr(DetailEnabled) {
454 static constexpr bool rotate=
true;
455 std::vector<std::string> counter_labels { std::string(
"Truth particles"),
456 std::string(
"with asso. track"),
457 std::string(
"with >1 asso. tracks"),
458 std::string(
"total tracks")};
459 std::vector<std::string> pt_labels;
460 pt_labels.reserve(statPtBins.size() + 2);
461 unsigned int pt_precision=0;
462 for (
float pt : statPtBins) {
468 for (std::size_t bin_i = 0; bin_i < statPtBins.size() + 2; ++bin_i) {
473 std::vector<std::string> eta_labels;
474 eta_labels.reserve(statEtaBins.size() + 2);
475 for (std::size_t eta_bin_i = 0; eta_bin_i < statEtaBins.size() + 2; ++eta_bin_i) {
479 accumulateToLastColumnRow(statPtBins.size()+2,statEtaBins.size()+2,
m_statPerEta);
480 accumulateToLastColumnRow(statPtBins.size()+2,statEtaBins.size()+2,
m_counterPerEta);
482 if (statPtBins.empty() || printDetails) {
489 : std::string(
"eta") ),
490 !statPtBins.empty());
492 if (!statPtBins.empty()) {
493 parent.printData2D(pt_labels, eta_labels,
504 if (pdgIdCategorisation) {
505 std::vector<std::string> pdg_id_labels;
506 pdg_id_labels.reserve( pdgId.size());
507 pdg_id_labels.push_back(
"Other");
508 for (
unsigned int pdg_i=1; pdg_i < pdgId.size(); ++pdg_i) {
509 std::stringstream a_label;
510 a_label << HepPID::particleName(pdgId[pdg_i]) <<
" [" << pdgId[pdg_i] <<
"]";
511 pdg_id_labels.push_back( a_label.str() );
513 unsigned int max_pdg_id_slots=
m_statPerPdgId.size()/(statPtBins.size()+2);
516 accumulateToLastRow(statPtBins.size()+2,max_pdg_id_slots,
m_statPerPdgId);
519 if (statPtBins.empty() || printDetails) {
526 : std::string(
"eta")),
527 !statPtBins.empty());
529 if (!statPtBins.empty()) {
530 parent.printData2D(pt_labels, pdg_id_labels,
546 msg() << MSG::INFO << std::endl;
549 std::array<std::string, kNCounter> counter_labels { std::string(
"Number of tracks"),
550 std::string(
"Number of truth particles with hit counts"),
551 std::string(
"Associated truth particles without hit counts"),
552 std::string(
"Tracks without associated truth particle"),
553 std::string(
"Tracks without selected, associated truth particle"),
554 std::string(
"Best truth particle without noise correction mismatch")
556 msg() <<
makeTable( m_counter, counter_labels) << std::endl;
565 const std::vector<std::string> &col_category_labels,
566 std::vector<std::string> &counter_labels,
567 std::vector< std::array< ActsUtils::Stat, kNCategorisedStat> > &stat_per_category,
568 std::vector< std::array< std::size_t, kNCategorisedCounter> > &counts_per_category,
569 const std::string &top_left,
570 bool print_sub_categories)
const {
571 if (!row_category_labels.empty() && !col_category_labels.empty()) {
572 if (row_category_labels.size() * col_category_labels.size() > counts_per_category.size() ) {
573 ATH_MSG_ERROR(
"Mismatch between category labels and number of counters (logic error -> fix needed):"
574 << row_category_labels.size() <<
" * " << col_category_labels.size()
575 <<
" > " << counts_per_category.size() );
577 constexpr std::size_t stat_column_width=14*4 + 3*3+4 + 9;
578 assert( stat_per_category.size() == counts_per_category.size());
579 const unsigned int n_rows = row_category_labels.size();
580 const unsigned int n_cols = stat_per_category.size() / n_rows;
583 assert( stat_per_category.size() % n_rows == 0 );
584 for(
unsigned int row_i=(print_sub_categories ? 0 : n_rows-1); row_i<n_rows; ++row_i) {
586 std::vector<std::string> stat_labels { std::string(
"Hit Efficiency") };
588 .columnWidth(stat_column_width)
589 .labelPrefix(row_category_labels.at(row_i)+
" ")
590 .precision(std::vector<unsigned int>{3})
594 std::vector<std::string> stat_labels { std::string(
"Hit Purity") };
596 .columnWidth(stat_column_width)
597 .labelPrefix(row_category_labels.at(row_i)+
" ")
598 .precision(std::vector<unsigned int>{3})
602 std::vector<std::string> stat_labels { std::string(
"Match probability") };
604 .columnWidth(stat_column_width)
605 .labelPrefix(row_category_labels.at(row_i)+
" ")
606 .precision(std::vector<unsigned int>{3})
611 .labelPrefix(row_category_labels.at(row_i)+
" ")
616 std::vector< std::array< float, 2> > eff;
617 eff.reserve(m_pdgId.size());
618 for (
unsigned int category_i=0; category_i< col_category_labels.size(); ++category_i) {
622 std::vector<std::string> eff_labels { std::string(
"reco efficiency"),
623 std::string(
"stat. uncertainty") };
624 msg() <<
makeTable( eff, 0u, eff.begin()->size(),0u,1u, col_category_labels, eff_labels, top_left)
625 .labelPrefix(row_category_labels.at(row_i)+
" ")
626 .precision(std::vector<unsigned int>{3,3})
635 template <
typename T>
636 struct TablePlusData {
637 TablePlusData(std::vector<T> &&values,
638 const std::vector<std::string> &row_labels,
639 const std::vector<std::string> &col_labels,
640 const std::string &top_left_label)
641 : m_data(
std::move(values)),
650 TableUtils::Range<std::string> {col_labels.data(), col_labels.size()},
654 std::vector<T> m_data;
655 TableUtils::MultiColumnTable<T> m_assocTable;
656 TablePlusData &columnWidth(std::size_t value) { m_assocTable.columnWidth(value);
return *
this;}
657 TablePlusData &minLabelWidth(std::size_t value) { m_assocTable.minLabelWidth(value);
return *
this;}
658 TablePlusData &dumpHeader(
bool value=
true) { m_assocTable.dumpHeader(value);
return *
this;}
659 TablePlusData &dumpFooter(
bool value=
true) { m_assocTable.dumpFooter(value);
return *
this;}
660 TablePlusData &separateLastRow(
bool value=
true) { m_assocTable.separateLastRow(value);
return *
this;}
661 TablePlusData &labelPrefix(
const std::string& value) { m_assocTable.labelPrefix(value);
return *
this;}
662 TablePlusData &precision(std::vector<unsigned int> &&precision) { m_assocTable.precision(std::move(precision));
return *
this;}
665 template <
typename T>
666 inline MsgStream &
operator<<(MsgStream &out,
const TablePlusData<T> &table) {
671 template <
typename T>
672 inline std::ostream &
operator<<(std::ostream &out,
const TablePlusData<T> &table) {
677 template <
class T_Container,
class T_Function,
typename T=
double>
679 create2DTable(
const std::vector<std::string> &row_category_labels,
680 const std::vector<std::string> &col_category_labels,
681 const std::string &top_left_label,
682 T_Container container,
685 const unsigned int n_rows = row_category_labels.size();
686 const unsigned int n_cols = col_category_labels.size();
687 const unsigned int n_cols_total =
container.size() / n_rows;
689 values.reserve( n_rows * n_cols );
691 for (
unsigned int col_i=0; col_i< n_cols; ++col_i) {
692 for (
unsigned int row_i=0; row_i< n_rows; ++row_i) {
693 values.push_back( function(
container.at( row_i * n_cols_total + col_i )) );
698 for (
unsigned int row_i=0; row_i< n_rows; ++row_i) {
699 for (
unsigned int col_i=0; col_i< n_cols; ++col_i) {
700 values.push_back( function(
container.at( row_i * n_cols_total + col_i )) );
704 return TablePlusData<T>(std::move(values),
705 rotate ? col_category_labels : row_category_labels,
706 rotate ? row_category_labels : col_category_labels,
712 const std::vector<std::string> &col_category_labels,
713 const std::string &top_left_label,
714 std::vector< std::array< ActsUtils::Stat, kNCategorisedStat> > &stat_per_category,
715 std::vector< std::array< std::size_t, kNCategorisedCounter> > &counts_per_category,
718 if (!row_category_labels.empty() && !col_category_labels.empty()) {
719 if (row_category_labels.size() * col_category_labels.size() > counts_per_category.size() ) {
720 ATH_MSG_ERROR(
"Mismatch between category labels and number of counters (logic error -> fix needed):"
721 << row_category_labels.size() <<
" * " << col_category_labels.size()
722 <<
" > " << counts_per_category.size() );
724 std::vector<unsigned int> column_precision;
725 column_precision.resize(
rotate ? row_category_labels.size() : col_category_labels.size(), 3u);
726 assert( stat_per_category.size() == counts_per_category.size());
727 msg() <<
"Hit efficiency : contributing hits over all hits of best matching truth particle" << std::endl
728 << create2DTable( row_category_labels, col_category_labels, top_left_label, stat_per_category,
729 [](
const std::array< ActsUtils::Stat, kNCategorisedStat> &stat) {
734 .precision(std::vector<unsigned int>(column_precision))
736 msg() <<
"Hit purity : contributing hits of best matching truth particle over all hits on track" << std::endl
737 << create2DTable( row_category_labels, col_category_labels, top_left_label, stat_per_category,
738 [](
const std::array< ActsUtils::Stat, kNCategorisedStat> &stat) {
743 .precision(std::vector<unsigned int>(column_precision))
745 msg() <<
"Match probability : weighted common hit sum of best matching truth particle over total track weighted hit sum" << std::endl
746 << create2DTable( row_category_labels, col_category_labels, top_left_label, stat_per_category,
747 [](
const std::array< ActsUtils::Stat, kNCategorisedStat> &stat) {
752 .precision(std::vector<unsigned int>(column_precision))
756 msg() <<
"Reco efficiency : tracks with assoc. truth particle over all selected truth particles with assoc. measurements."
758 << create2DTable( row_category_labels, col_category_labels, top_left_label, counts_per_category,
759 [](
const std::array< std::size_t, kNCategorisedCounter> &counter) {
765 .precision(std::move(column_precision))
773 ATH_MSG_FATAL(
"There must be exactly one weight per measurement type. But got "
775 return StatusCode::FAILURE;
778 ATH_MSG_FATAL(
"There must be exactly one weight for computing the matching probability per measurement type. But got "
780 return StatusCode::FAILURE;
784 ATH_MSG_FATAL(
"Invalid weights (should be positive) or inconsistency of weights which are zero (match prob. weights, weights):"
786 return StatusCode::FAILURE;
789 return StatusCode::SUCCESS;
793 const std::vector<float> &
weights) {
794 assert(
weights.size() == counts.size());
796 for (
unsigned int count_i=0; count_i < counts.size(); ++count_i) {
797 sum += counts[count_i] *
weights[count_i];
803 const std::vector<float> &
weights) {
804 assert(
weights.size() == noise_counts.size());
806 for (
unsigned int count_i=0; count_i < noise_counts.size(); ++count_i) {
807 sum -=
weights[count_i] * noise_counts[count_i] - noise_counts[count_i];
Scalar eta() const
pseudorapidity method
#define ATH_CHECK
Evaluate an expression and check for errors.
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
size_t size() const
Number of registered mappings.
void rotate(double angler, GeoTrf::Vector2D &vector)
TableUtils::StatTable< T > makeTable(const std::array< T, N > &counter, const std::array< std::string, N > &label)
Container for hit counts per track Contains hit counts per associated truth particle and the total hi...
const container & countsPerTruthParticle() const
vector with counts per associated truth particle (read only)
HitCounterArray & noiseCounts()
Noise hit counts per track.
HitCounterArray & totalCounts()
Total hit counts per track.
void checkBinOrder(const std::vector< float > &bin_edges, const std::string &bin_label) const
check that bins are in increasing order.
static constexpr unsigned int s_NMeasurementTypes
static constexpr int s_pdgIdMax
void printData2D(const std::vector< std::string > &row_category_labels, const std::vector< std::string > &col_category_labels, const std::string &top_left_label, std::vector< std::array< ActsUtils::Stat, kNCategorisedStat > > &stat_per_category, std::vector< std::array< std::size_t, kNCategorisedCounter > > &counts_per_category, bool rotate) const
SG::ReadHandleKey< TruthParticleHitCounts > m_truthHitCounts
TruthMatchResult analyseTrackTruth(const TruthParticleHitCounts &truth_particle_hit_counts, const HitCountsPerTrack &track_hit_counts, EventStat &event_stat) const
DebugCounter< TrackFindingValidationDebugHists > m_debugCounter
void printCategories(const std::vector< std::string > &pt_category_labels, const std::vector< std::string > &eta_category_labels, std::vector< std::string > &counter_labels, std::vector< std::array< ActsUtils::Stat, kNCategorisedStat > > &stat_per_category, std::vector< std::array< std::size_t, kNCategorisedCounter > > &counts_per_category, const std::string &top_left_label, bool print_sub_categories) const
StatusCode checkMatchWeights()
EventStatBase< TrackFindingValidationDetailedStat > EventStat
static double noiseCorrection(const ActsTrk::HitCounterArray &noise_counts, const std::vector< float > &weights)
std::size_t getPtPdgIdStatCategory(float pt, int pdg_id) const
Return the category based on the PDG ID.
static double weightedCountSum(const ActsTrk::HitCounterArray &counts, const std::vector< float > &weights)
@ NoAssociatedTruthParticle
@ TruthParticleNoNoiseMismatch
@ MissingTruthParticleHitCounts
@ NoSelectedTruthParticle
Property< std::vector< float > > m_statPtBins
Property< bool > m_showRawCounts
void postProcessEventStat(const TruthParticleHitCounts &truth_particle_hit_counts, std::size_t n_tracks, EventStat &event_stat) const
Gaudi::Property< std::vector< float > > m_weightsForProb
void printStatTables() const
std::size_t getPtEtaStatCategory(float pt, float eta) const
Return the category based on the provided eta value.
TrackTruthMatchingBaseAlg(const std::string &name, ISvcLocator *pSvcLocator)
Property< bool > m_computeTrackRecoEfficiency
Property< bool > m_pdgIdCategorisation
@ kNParticleWithAssociatedTrack
Property< std::vector< float > > m_statEtaBins
Property< bool > m_printDetails
virtual StatusCode initialize() override
Gaudi::Property< std::vector< float > > m_weights
virtual StatusCode finalize() override
ToolHandle< IAthSelectionTool > m_truthSelectionTool
void add(double val)
Gather statistics and fill the histogram if not disabled.
bool msgLvl(const MSG::Level lvl) const
An algorithm that can be simultaneously executed in multiple threads.
int pdg_id() const
PDG ID code.
virtual double pt() const override final
The transverse momentum ( ) of the particle.
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
std::string tail(std::string s, const std::string &pattern)
tail of a string
std::string head(std::string s, const std::string &pattern)
head of a string
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
std::unordered_map< const xAOD::TruthParticle *, HitCounterArray > TruthParticleHitCounts
constexpr bool TrackFindingValidationDetailedStat
std::ostream & operator<<(std::ostream &ostr, const DetectorType type)
Pipe the detector type to an outstream object.
constexpr bool TrackFindingValidationDebugHists
void dumpStat(T_Stream &out, const Stat &stat)
Dump the given statistics object to the given output stream.
const SG::AuxVectorData * container() const
Return the container holding this element.
float computeRatio(std::size_t numerator, std::size_t denominator)
std::size_t maxLabelWidth(const T_Collection &col)
std::string makeEtaBinLabel(const std::vector< float > &eta_bins, std::size_t eta_bin_i, bool abs_eta=false)
std::string makeBinLabel(const std::string &variable_name, const std::vector< float > &bins, std::size_t bin_i, bool abs_value=false, int precision=1)
TruthParticle_v1 TruthParticle
Typedef to implementation.
void incrementTotal(unsigned int eta_category_i, unsigned int pdg_id_category_i)
BaseStat< DetailEnabled > & operator+=(const BaseStat< DetailEnabled > &event_stat)
StatArrayVec m_statPerPdgId
CounterArrayVec m_counterPerPdgId
StatArrayVec m_statPerEta
ActsUtils::StatHist m_truthSelectionCuts
CounterArrayVec m_counterPerEta
void printStatTables(const TrackTruthMatchingBaseAlg &parent, const std::vector< float > &statPtBins, const std::vector< float > &statEtaBins, std::vector< int > &pdgId, bool printDetails, bool pdgIdCategorisation, bool useAbsEtaForStat)
void fillMeasForTruthParticleWithoutCount(double weighted_measurement_sum) const
void dumpStatistics(T_OutStream &out) const
void fillTruthMatchProb(const std::array< float, 2 > &best_match_prob) const
unsigned int m_nTruthParticleWithoutAssociatedCounts
static constexpr bool doDetail
unsigned int m_nTracksWithoutAssociatedTruthParticle
unsigned int m_nTruthCuts
unsigned int m_nTracksWithoutSelectedTruthParticle
void fill(unsigned int eta_category_i, unsigned int pdg_id_category_i, float hit_efficiency, float hit_purity, float match_prob, const xAOD::TruthParticle *best_match)
unsigned int m_nTruthParticleNonoiseMismatches
Match result returned by analyseTrackTruth.
float m_hitPurity
fraction of hits originting from best match over total reco hits
float m_matchProbability
the matching probability based on weighted hit sums
float m_hitEfficiency
fraction of hits originting from best match over total best match hits
const xAOD::TruthParticle * m_truthParticle
best matching truth particle or nullptr