10 #include "art/Framework/Core/EDAnalyzer.h"
11 #include "art/Framework/Core/ModuleMacros.h"
12 #include "art/Framework/Principal/Event.h"
13 #include "art/Framework/Principal/Handle.h"
14 #include "art/Framework/Services/Registry/ServiceHandle.h"
15 #include "art_root_io/TFileService.h"
16 #include "canvas/Persistency/Common/FindManyP.h"
17 #include "fhiclcpp/ParameterSet.h"
48 void analyze(art::Event
const&
e)
override;
90 e.getByLabel(producer, h);
93 msg +=
"Could not find a data product by: " + producer;
225 msg +=
"\033[93m[ERROR]\033[00m <<";
227 msg +=
">> Producer's name not set!";
229 throw ::showerreco::ShowerRecoException(msg.c_str());
232 art::ServiceHandle<geo::Geometry const> geo;
233 art::ServiceHandle<art::TFileService const>
tfs;
236 fTree = tfs->make<TTree>(
"fShowerQualityTree",
"");
243 tfs->make<TH1D>(
"hMatchCorrectness",
244 "Shower 2D Cluster Matching Correctness; Correctness; Showers",
258 "hVtxDX",
"Reco - MC Start X [cm] Displacement; #DeltaX [cm]; Showers", 200, -100, 100);
261 "hVtxDY",
"Reco - MC Start Y [cm] Displacement; #DeltaY [cm]; Showers", 200, -100, 100);
264 "hVtxDZ",
"Reco - MC Start Z [cm] Displacement; #DeltaZ [cm]; Showers", 200, -100, 100);
267 "hVtxDR",
"Reco - MC Start 3D Vtx Displacement; #DeltaR [cm]; Showers", 200, -100, 100);
278 "hDCosX",
"Direction Unit Vector Reco - MC #DeltaX; #DeltaCosX; Showers", 100, -2, 2);
281 "hDCosY",
"Direction Unit Vector Reco - MC #DeltaY; #DeltaCosY; Showers", 100, -2, 2);
284 "hDCosZ",
"Direction Unit Vector Reco - MC #DeltaZ; #DeltaCosZ; Showers", 100, -2, 2);
287 tfs->make<TH1D>(
"h3DAngleDiff",
288 "3D Opening Angle Between Reco & MC; Opening Angle [degrees]; Showers",
301 tfs->make<TH2D>(
"hEnergyCorr",
302 "Reco (x) vs. MC (y) Energy Comparison; Reco Energy [MeV]; MC Energy [MeV]",
311 "MC - Reco Energy Fractional Difference; Assymetry; Showers",
317 "hEnergyDiff",
"MC - Reco Energy Difference; Energy Difference [MeV]; Showers", 200, 0, 1000);
326 tfs->make<TH1D>(
"hMatchedClusterEff_PlaneCombo",
327 "Matched Shower Cluster's Charge Efficiency; Efficiency; Clusters",
333 "Matched Shower Cluster's Charge Purity; Purity; Clusters",
342 "Best Plane (for energy & dE/dx estimate); Plane ID; Showers",
345 geo->Nplanes() - 0.5);
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;
364 art::Handle<std::vector<recob::Cluster>> clsHandle;
365 art::FindManyP<recob::Cluster> cluster_m(resHandle, e,
fShowerProducer);
366 e.get(cluster_m.at(0).front().id(), clsHandle);
367 if (!clsHandle.isValid())
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) {
377 const art::Ptr<recob::Cluster> cluster_ptr(clsHandle, 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);
411 auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(e);
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 SetSimChannelProducer(const std::string name)
void SetMinEnergyCut(const double energy)
Set minimum energy for MCShowers to be considered.
BEGIN_PROLOG could also be cerr
TH1D * h3DAngleDiff
Opening angle between reco & MC 3D direction.
Class def header for a class MCMatchAlg.
Declaration of signal hit object.
ShowerQuality(fhicl::ParameterSet const &p)
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.
void SetShowerProducer(const std::string name)
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.
art::Handle< T > GetDataOrDie(art::Event const &e, std::string producer)
double _mc_energy_min
Minimum MC shower energy cut.
For convenience: struct to define a set of parameters per shower to be stored in TTree.
void SetMaxEnergyCut(const double energy)
Set maximum energy for MCShowers to be considered.
Declaration of cluster object.
TH2D * hEnergyCorr
Energy correlation reco (x) vs. MC (y)
ShowerQuality & operator=(ShowerQuality const &)=delete
struct ShowerQuality::TreeParams_t fTreeParams
void InitializeAnaTree()
Function to prepare TTree.
void SetMCShowerProducer(const std::string name)
Class def header for MCShower data container.
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)
art::ServiceHandle< art::TFileService > tfs
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.
void analyze(art::Event const &e) override
TH1D * hBestPlane
Best plane id.
art framework interface to geometry description
BEGIN_PROLOG could also be cout
Class def header for exception classes in ShowerReco3D package.