355 auto resHandle = GetDataOrDie<std::vector<recob::Shower>>(
e,
fShowerProducer);
357 const std::vector<sim::MCShower>& ev_mcs(*mcsHandle);
358 const std::vector<recob::Shower>& ev_shower(*resHandle);
359 const std::vector<sim::SimChannel>& ev_simch(*schHandle);
361 if (!(ev_shower.size()))
return;
365 art::FindManyP<recob::Cluster> cluster_m(resHandle, e,
fShowerProducer);
366 e.get(cluster_m.at(0).front().id(), clsHandle);
368 throw ::showerreco::ShowerRecoException(
"Failed to retrieve cluster handle!");
369 const std::vector<recob::Cluster>& ev_cluster(*clsHandle);
372 art::FindManyP<recob::Hit> hit_m(clsHandle, e, clsHandle.
provenance()->moduleLabel());
373 std::vector<std::vector<art::Ptr<recob::Hit>>> ev_cluster_hit;
374 ev_cluster_hit.reserve(clsHandle->size());
375 std::map<art::Ptr<recob::Cluster>,
size_t> cluster_ptr_map;
376 for (
size_t i = 0; i < ev_cluster.size(); ++i) {
378 cluster_ptr_map[cluster_ptr] = ev_cluster_hit.size();
379 ev_cluster_hit.push_back(hit_m.at(i));
383 std::vector<std::vector<unsigned int>> ass_cluster_v;
384 ass_cluster_v.reserve(ev_shower.size());
385 for (
size_t shower_index = 0; shower_index < ev_shower.size(); ++shower_index) {
386 ass_cluster_v.push_back(std::vector<unsigned int>());
387 for (
auto const&
p : cluster_m.at(shower_index))
388 ass_cluster_v.back().push_back(cluster_ptr_map[
p]);
392 std::vector<std::vector<unsigned int>> g4_trackid_v;
393 std::vector<unsigned int> mc_index_v;
394 g4_trackid_v.reserve(ev_mcs.size());
395 for (
size_t mc_index = 0; mc_index < ev_mcs.size(); ++mc_index) {
396 auto const& mcs = ev_mcs[mc_index];
397 double energy = mcs.DetProfile().E();
398 std::vector<unsigned int> id_v;
399 id_v.reserve(mcs.DaughterTrackID().size());
401 for (
auto const&
id : mcs.DaughterTrackID()) {
402 if (
id == mcs.TrackID())
continue;
405 id_v.push_back(mcs.TrackID());
406 g4_trackid_v.push_back(id_v);
407 mc_index_v.push_back(mc_index);
412 if (!
fBTAlg.
BuildMap(clockData, g4_trackid_v, ev_simch, ev_cluster_hit)) {
413 std::cerr <<
"\033[93m[ERROR]\033[00m <<ShowerQuality::analyze>> Failed to " 414 "build back-tracking map for MC..." 420 std::vector<std::vector<double>> shower_mcq_vv(ev_shower.size(),
421 std::vector<double>(mc_index_v.size(), 0));
423 for (
size_t shower_index = 0; shower_index < ass_cluster_v.size(); ++shower_index) {
425 auto const& ass_cluster = ass_cluster_v[shower_index];
427 std::vector<::btutil::WireRange_t> w_v;
429 for (
auto const& cluster_index : ass_cluster) {
431 auto const& ass_hit = ev_cluster_hit[cluster_index];
433 w_v.reserve(ass_hit.size() + w_v.size());
435 for (
auto const& hit_ptr : ass_hit) {
436 w_v.emplace_back(hit_ptr->Channel(), hit_ptr->StartTick(), hit_ptr->EndTick());
442 auto& shower_mcq_v = shower_mcq_vv[shower_index];
444 for (
size_t mcs_index = 0; mcs_index < (mcq_v.size() - 1); ++mcs_index) {
446 shower_mcq_v[mcs_index] = mcq_v[mcs_index];
451 for (
size_t mcs_index = 0; mcs_index < mc_index_v.size(); ++mcs_index) {
453 auto const& mc_shower = ev_mcs[mc_index_v[mcs_index]];
456 size_t best_shower_index = shower_mcq_vv.size();
458 for (
size_t shower_index = 0; shower_index < shower_mcq_vv.size(); ++shower_index) {
460 if (shower_mcq_vv[shower_index][mcs_index] > max_mcq) best_shower_index = shower_index;
463 if (best_shower_index == shower_mcq_vv.size()) {
465 std::cerr <<
"\033[93m[ERROR]\033[00m <<ShowerQuality::analyze>> " 466 <<
"Failed to find a corresponding shower for MCShower " << mc_index_v[mcs_index]
471 auto const& reco_shower = ev_shower[best_shower_index];
478 std::cerr <<
"\033[93m[ERROR]\033[00m <<ShowerQuality::analyze>> " 479 <<
"Failed to find a corresponding MCShower for shower " << best_shower_index
514 3.14159265359 * 180.;
523 for (
auto const& cluster_index : ass_cluster_v[best_shower_index]) {
525 if (ep.first == 0 && ep.second == 0)
continue;
584 mDEDX.insert(std::make_pair(
TH1D * hMatchedClusterPur
Matched 3D shower's cluster purity (combined across planes)
TH1D * hVtxDR
3D vtx distance between reco to MC in cm
void msg(const char *fmt,...)
TH1D * h3DAngleDiff
Opening angle between reco & MC 3D direction.
std::map< int, TH1D * > mDEDX
dEdx per particle per PDG code
const MCBTAlg & BTAlg() const
BTAlgo getter.
TH1D * hVtxDZ
Z difference (reco-MC) in cm.
std::string fMCShowerProducer
MCShower Producer's Name.
TH1D * hVtxDX
X difference (reco-MC) in cm.
bool BuildMap(detinfo::DetectorClocksData const &clockData, const std::vector< unsigned int > &g4_trackid_v, const std::vector< sim::SimChannel > &simch_v, const std::vector< std::vector< art::Ptr< recob::Hit >>> &cluster_v)
Constructs needed information for Reco=>MC matching.
TH1D * hDCosX
Direction unit vector X component difference.
TH1D * hVtxDY
Y difference (reco-MC) in cm.
bool isValid() const noexcept
TH1D * hEnergyAssym
Energy assym. parameter: (reco E - MC E) / (reco E + MC E) * 2.
std::pair< double, double > ClusterEP(const size_t cluster_index, const size_t mcshower_index) const
For a specified cluster, compute cluster efficiency and purity in terms of specified MC object...
TH1D * hEnergyDiff
Energy difference: reco E - MC E.
std::string fShowerProducer
Shower Producer's Name.
std::vector< double > MCQ(detinfo::DetectorClocksData const &clockData, const WireRange_t &hit) const
::btutil::MCMatchAlg fBTAlg
Shower back tracking algorithm.
Provenance const * provenance() const
double _mc_energy_min
Minimum MC shower energy cut.
TH2D * hEnergyCorr
Energy correlation reco (x) vs. MC (y)
struct ShowerQuality::TreeParams_t fTreeParams
TTree * fTree
Analysis TTree.
TH1D * hMatchCorrectness
Matching correctness.
TH1D * hDCosZ
Direction unit vector Z component difference.
double _mc_energy_max
Maximum MC shower energy cut.
TH1D * hMatchedClusterEff
Matched 3D shower's cluster efficiency (combined across planes)
std::pair< size_t, double > ShowerCorrectness(const std::vector< unsigned int > cluster_indices) const
TH1D * hDCosY
Direction unit vector Y component difference.
std::string fSimChannelProducer
SimChannel Producer's Name.
TH1D * hBestPlane
Best plane id.
QTextStream & endl(QTextStream &s)