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/Principal/Run.h"
15 #include "art/Framework/Principal/SubRun.h"
16 #include "canvas/Utilities/InputTag.h"
17 #include "fhiclcpp/ParameterSet.h"
18 #include "messagefacility/MessageLogger/MessageLogger.h"
20 #include "art/Framework/Services/Registry/ServiceHandle.h"
32 #include "art_root_io/TFileService.h"
49 #include "nusimdata/SimulationBase/MCParticle.h"
50 #include "nusimdata/SimulationBase/MCTruth.h"
60 class NuMuEfficiencyStudy;
78 const std::vector<geoalgo::AABox> &boxes);
81 const simb::MCParticle &genie_part,
82 const simb::MCTruth &mctruth,
83 const std::vector<art::Ptr<simb::MCParticle>> &g4_mcparticles,
84 const std::vector<const sim::GeneratedParticleInfo *> infos);
99 void analyze(art::Event
const&
e)
override;
113 bool InFV(TVector3 pos);
119 void FillTrue(
Histos &
h,
const simb::MCTruth &interaction,
const simb::MCParticle &G4lepton);
130 if (FV.ContainsPosition(pos))
return true;
136 InitHisto(fTruth,
"truth");
138 std::array<std::string, n_reco_eff> effnames {
"has_muon",
146 "has_fid_pure_slice",
147 "has_reco_fid_slice",
148 "slice_has_reco_muon",
151 "has_neutrino_slice"};
152 for (
unsigned i = 0; i < n_reco_eff; i++) {
153 for (
unsigned j = 0; j < n_reco_eff; j++) {
155 if (i == j) name = effnames[i];
156 else name = effnames[i] +
"_" + effnames[j];
157 fReco.emplace_back();
158 InitHisto(fReco.back(),
name);
164 art::ServiceHandle<art::TFileService>
tfs;
166 h.
neutrino_energy = tfs->make<TH1D>((prefix +
"_nuE").c_str(),
"nuE", 100, 0, 4);
167 h.
muon_momentum = tfs->make<TH1D>((prefix +
"_muP").c_str(),
"muP", 100, 0, 4);
168 h.
muon_length = tfs->make<TH1D>((prefix +
"_muL").c_str(),
"muL", 100, 0, 600);
170 float XMin = std::min_element(fFiducialVolumes.begin(), fFiducialVolumes.end(), [](
auto &lhs,
auto &rhs) {
return lhs.MinX() < rhs.MinX(); })->MinX();
171 float XMax = std::max_element(fFiducialVolumes.begin(), fFiducialVolumes.end(), [](
auto &lhs,
auto &rhs) {
return lhs.MaxX() < rhs.MaxX(); })->MaxX();
172 float YMin = std::min_element(fFiducialVolumes.begin(), fFiducialVolumes.end(), [](
auto &lhs,
auto &rhs) {
return lhs.MinY() < rhs.MinY(); })->MinY();
173 float YMax = std::max_element(fFiducialVolumes.begin(), fFiducialVolumes.end(), [](
auto &lhs,
auto &rhs) {
return lhs.MaxY() < rhs.MaxY(); })->MaxY();
174 float ZMin = std::min_element(fFiducialVolumes.begin(), fFiducialVolumes.end(), [](
auto &lhs,
auto &rhs) {
return lhs.MinZ() < rhs.MinZ(); })->MinZ();
175 float ZMax = std::max_element(fFiducialVolumes.begin(), fFiducialVolumes.end(), [](
auto &lhs,
auto &rhs) {
return lhs.MaxZ() < rhs.MaxZ(); })->MaxZ();
177 h.
vertex_x = tfs->make<TH1D>((prefix +
"_v_x").c_str(),
"v_x", 200, XMin, XMax);
178 h.
vertex_y = tfs->make<TH1D>((prefix +
"_v_y").c_str(),
"v_y", 200, YMin, YMax);
179 h.
vertex_z = tfs->make<TH1D>((prefix +
"_v_z").c_str(),
"v_z", 200, ZMin, ZMax);
181 h.
muon_completeness = tfs->make<TH1D>((prefix +
"_muC").c_str(),
"muC", 100, 0., 1.);
182 h.
muon_purity = tfs->make<TH1D>((prefix +
"_mupur").c_str(),
"mupur", 100, 0., 1.);
184 h.
slice_completeness = tfs->make<TH1D>((prefix +
"_nuC").c_str(),
"nuC", 100, 0., 1.);
185 h.
slice_purity = tfs->make<TH1D>((prefix +
"_nupur").c_str(),
"nupur", 100, 0., 1.);
190 fFiducialInset({
p.get<
float>(
"xmin"),
p.get<
float>(
"xmax"),
p.get<
float>(
"ymin"),
p.get<
float>(
"ymax"),
p.get<
float>(
"zmin"),
p.get<
float>(
"zmax")})
199 tend = geometry->
end_TPC(cryo.ID());
200 std::vector<geo::BoxBoundedGeo> this_tpc_volumes;
201 while (iTPC != tend) {
206 fTPCVolumes.push_back(std::move(this_tpc_volumes));
210 for (
const std::vector<geo::BoxBoundedGeo> &tpcs: fTPCVolumes) {
211 double XMin = std::min_element(tpcs.begin(), tpcs.end(), [](
auto &lhs,
auto &rhs) {
return lhs.MinX() < rhs.MinX(); })->MinX();
212 double YMin = std::min_element(tpcs.begin(), tpcs.end(), [](
auto &lhs,
auto &rhs) {
return lhs.MinY() < rhs.MinY(); })->MinY();
213 double ZMin = std::min_element(tpcs.begin(), tpcs.end(), [](
auto &lhs,
auto &rhs) {
return lhs.MinZ() < rhs.MinZ(); })->MinZ();
215 double XMax = std::max_element(tpcs.begin(), tpcs.end(), [](
auto &lhs,
auto &rhs) {
return lhs.MaxX() < rhs.MaxX(); })->MaxX();
216 double YMax = std::max_element(tpcs.begin(), tpcs.end(), [](
auto &lhs,
auto &rhs) {
return lhs.MaxY() < rhs.MaxY(); })->MaxY();
217 double ZMax = std::max_element(tpcs.begin(), tpcs.end(), [](
auto &lhs,
auto &rhs) {
return lhs.MaxZ() < rhs.MaxZ(); })->MaxZ();
219 fActiveVolumes.emplace_back(XMin, XMax, YMin, YMax, ZMin, ZMax);
220 fFiducialVolumes.emplace_back(XMin + fFiducialInset[0], XMax - fFiducialInset[1],
221 YMin + fFiducialInset[2], YMax - fFiducialInset[3],
222 ZMin + fFiducialInset[4], ZMax - fFiducialInset[5]);
229 std::vector<geoalgo::AABox> aa_volumes;
231 if (AV.ContainsPosition(particle.Position().Vect())) {
232 aa_volumes.emplace_back(AV.MinX(), AV.MinY(), AV.MinZ(), AV.MaxX(), AV.MaxY(), AV.MaxZ());
238 for (
unsigned i = 1; i < particle.NumberTrajectoryPoints(); i++) {
239 length +=
ContainedLength(particle.Position(i-1).Vect(), particle.Position(i).Vect(), aa_volumes);
257 h.
muon_momentum->Fill(truth.GetNeutrino().Lepton().Momentum().Vect().Mag());
260 h.
vertex_x->Fill(truth.GetNeutrino().Nu().Position().X());
261 h.
vertex_y->Fill(truth.GetNeutrino().Nu().Position().Y());
262 h.
vertex_z->Fill(truth.GetNeutrino().Nu().Position().Z());
267 art::ServiceHandle<cheat::BackTrackerService> backtracker;
268 art::ServiceHandle<cheat::ParticleInventoryService> inventory_service;
270 auto const clock_data = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(ev);
272 art::ValidHandle<std::vector<simb::MCTruth>> mctruth_handle = ev.getValidHandle<std::vector<simb::MCTruth>>(
"generator");
273 const std::vector<simb::MCTruth> &mctruth_list = *mctruth_handle;
274 std::vector<art::Ptr<simb::MCTruth>> mctruth_ptrs;
275 art::fill_ptr_vector(mctruth_ptrs, mctruth_handle);
277 art::FindManyP<simb::MCParticle, sim::GeneratedParticleInfo> truth_to_particles(mctruth_handle, ev,
"largeant");
278 const std::vector<simb::MCParticle> &g4_particles = *ev.getValidHandle<std::vector<simb::MCParticle>>(
"largeant");
279 std::map<int, const simb::MCParticle*> g4_particle_map;
280 for (
unsigned i_g4 = 0; i_g4 < g4_particles.size(); i_g4++) {
281 g4_particle_map[g4_particles[i_g4].TrackId()] = &g4_particles[i_g4];
284 std::vector<int> truth_to_numucc;
285 std::vector<simb::MCTruth> numucc;
286 std::vector<simb::MCParticle> G4muons;
288 for (
unsigned i = 0; i < mctruth_list.size(); i++) {
289 const simb::MCTruth &truth = mctruth_list[i];
290 TVector3
vertex(truth.GetNeutrino().Nu().Position().X(), truth.GetNeutrino().Nu().Position().Y(), truth.GetNeutrino().Nu().Position().Z());
292 if (
InFV(
vertex) && truth.GetNeutrino().CCNC() == 0 &&
abs(truth.GetNeutrino().Nu().PdgCode()) == 14) {
294 const simb::MCParticle *G4muon =
Genie2G4MCParticle(truth.GetNeutrino().Lepton(), truth, truth_to_particles.at(i), truth_to_particles.data(i));
295 FillTrue(fTruth, truth, *G4muon);
296 numucc.push_back(truth);
297 G4muons.push_back(*G4muon);
298 truth_to_numucc.push_back(numucc.size()-1);
300 else truth_to_numucc.push_back(-1);
304 if (numucc.size() == 0)
return;
307 std::vector<float> muonVisE(G4muons.size(), 0.);
308 for (
unsigned i = 0; i < G4muons.size(); i++) {
309 std::vector<const sim::IDE*> particle_ides(backtracker->TrackIdToSimIDEs_Ps(G4muons[i].TrackId()));
310 for (
const sim::IDE *ide: particle_ides) muonVisE[i] += ide->energy / 1000.;
314 std::vector<float> numuVisE(numucc.size(), 0.);
315 for (
unsigned i_g4 = 0; i_g4 < g4_particles.size(); i_g4++) {
316 const simb::MCParticle &particle = g4_particles[i_g4];
317 if (particle.Process() !=
"primary")
continue;
318 art::Ptr<simb::MCTruth> truth = inventory_service->TrackIdToMCTruth_P(particle.TrackId());
319 for (
unsigned i_truth = 0; i_truth < mctruth_ptrs.size(); i_truth++) {
320 if (truth == mctruth_ptrs[i_truth]) {
321 if (truth_to_numucc[i_truth] != -1) {
322 std::vector<const sim::IDE*> particle_ides(backtracker->TrackIdToSimIDEs_Ps(particle.TrackId()));
323 for (
const sim::IDE *ide: particle_ides) numuVisE[truth_to_numucc[i_truth]] += ide->energy / 1000.;
333 std::vector<int> matching_track(G4muons.size(), -1);
334 std::vector<float> track_purity(G4muons.size(), -1);
335 std::vector<float> track_completeness(G4muons.size(), -1);
337 art::ValidHandle<std::vector<recob::PFParticle>> particle_handle = ev.getValidHandle<std::vector<recob::PFParticle>>(
"pandora");
338 art::FindManyP<recob::Track>
tracks(particle_handle, ev,
"pandoraTrack");
339 art::FindManyP<larpandoraobj::PFParticleMetadata> metadatas(particle_handle, ev,
"pandora");
340 art::FindManyP<recob::Vertex> particles_to_vertex(particle_handle, ev,
"pandora");
341 for (
unsigned i_part = 0; i_part < particle_handle->size(); i_part++) {
342 if (!tracks.at(i_part).size())
continue;
343 art::FindManyP<recob::Hit> fmHits(tracks.at(i_part), ev,
"pandoraTrack");
344 const std::vector<art::Ptr<recob::Hit>> &this_hits = fmHits.at(0);
349 std::sort(matches.begin(), matches.end(),
350 [] (
auto const &lhs,
auto const &rhs) {
return lhs.second > rhs.second; });
352 for (
unsigned i_cc = 0; i_cc < G4muons.size(); i_cc++) {
353 if (matches.size() && matches[0].first == G4muons[i_cc].TrackId() && matches[0].second / muonVisE[i_cc] > 0.5) {
354 matching_track[i_cc] = particle_handle->at(i_part).Self();
355 track_purity[i_cc] = matches[0].second /
356 std::accumulate(matches.begin(), matches.end(), 0.f,
357 [](
auto &
a,
auto &b){
return a + b.second;});
358 track_completeness[i_cc] = matches[0].second / muonVisE[i_cc];
364 std::vector<int> matching_slice(numucc.size(), -1);
365 std::vector<float> matching_purity(numucc.size(), -1);
366 std::vector<float> matching_completeness(numucc.size(), -1);
368 art::ValidHandle<std::vector<recob::Slice>> slice_handle = ev.getValidHandle<std::vector<recob::Slice>>(
"pandora");
369 art::FindManyP<recob::Hit> slice_hits(slice_handle, ev,
"pandora");
370 art::FindManyP<recob::PFParticle> slice_particles(slice_handle, ev,
"pandora");
372 for (
unsigned i_slice = 0; i_slice < slice_handle->size(); i_slice++) {
373 std::vector<float> matchingE(numuVisE.size(), 0.);
374 std::vector<float> matchingPrimaryE(numuVisE.size(), 0.);
378 for (
unsigned i_match = 0; i_match < matches.size(); i_match++) {
379 totalE += matches[i_match].second / 1000.;
382 for (
unsigned i_match = 0; i_match < matches.size(); i_match++) {
383 if (g4_particle_map.count(matches[i_match].first)) {
384 const simb::MCParticle &part = *g4_particle_map.at(matches[i_match].
first);
385 art::Ptr<simb::MCTruth> truth = inventory_service->TrackIdToMCTruth_P(part.TrackId());
386 for (
unsigned i_truth = 0; i_truth < mctruth_ptrs.size(); i_truth++) {
387 if (truth == mctruth_ptrs[i_truth]) {
388 if (truth_to_numucc[i_truth] != -1) {
389 if (part.Process() ==
"primary") matchingPrimaryE[truth_to_numucc[i_truth]] += matches[i_match].
second / 1000.;
390 matchingE[truth_to_numucc[i_truth]] += matches[i_match].second / 1000.;
398 unsigned best_match =
std::distance(matchingE.begin(), std::max_element(matchingE.begin(), matchingE.end()));
399 if (matchingPrimaryE[best_match] / numuVisE[best_match] > 0.5) {
400 matching_slice[best_match] = i_slice;
401 matching_purity[best_match] = matchingE[best_match] / totalE;
402 matching_completeness[best_match] = matchingPrimaryE[best_match] / numuVisE[best_match];
407 for (
unsigned i = 0; i < numucc.size(); i++) {
408 bool has_muon_track = matching_track[i] != -1;
409 bool has_slice = matching_slice[i] != -1;
411 bool has_pure_slice = has_slice && matching_purity[i] > 0.5;
413 bool muon_is_reco =
false;
414 bool muon_is_fid =
false;
415 if (has_muon_track) {
419 for (
auto pair: properties)
std::cout << pair.first << std::endl;
420 if (properties.count(
"IsClearCosmic")) {
421 muon_is_reco =
false;
427 auto muon_vert = tracks.at(matching_track[i]).at(0)->Start();
428 TVector3 muon_vert_v(muon_vert.X(), muon_vert.Y(), muon_vert.Z());
430 muon_is_fid =
InFV(muon_vert_v);
433 bool slice_is_neutrino =
false;
434 bool slice_is_reco =
false;
435 bool slice_is_fiducial =
false;
436 bool slice_has_muon =
false;
438 const std::vector<art::Ptr<recob::PFParticle>> &this_slice_particles = slice_particles.at(matching_slice[i]);
439 for (art::Ptr<recob::PFParticle> pfp: this_slice_particles) {
440 if (pfp->IsPrimary()) {
444 for (
auto pair: properties)
std::cout << pair.first <<
" " << pair.second << std::endl;
446 if (properties.count(
"IsNeutrino")) slice_is_neutrino =
true;
447 if (properties.count(
"IsNeutrino") && pfp->PdgCode() == 14) slice_is_reco =
true;
450 if (particles_to_vertex.at(pfp.key()).
size()) {
451 const recob::Vertex &vert = *particles_to_vertex.at(pfp.key()).at(0);
453 slice_is_fiducial =
InFV(vect);
456 if (has_muon_track && matching_track[i] == (
int)pfp->Self()) {
457 slice_has_muon =
true;
462 bool has_pure_nu_slice = has_pure_slice && slice_is_neutrino;
463 bool has_fid_nu_slice = slice_is_fiducial && slice_is_neutrino;
464 bool has_fid_pure_slice = slice_is_fiducial && has_pure_slice;
465 bool has_reco_fid_slice = slice_is_fiducial && slice_is_reco;
466 bool slice_has_reco_muon = slice_has_muon && muon_is_reco;
468 std::array<bool, n_reco_eff> pass = {has_muon_track, muon_is_reco, muon_is_fid, has_slice, has_pure_slice, slice_is_reco, slice_is_fiducial, slice_has_muon, has_fid_pure_slice, has_reco_fid_slice, slice_has_reco_muon, has_fid_nu_slice, has_pure_nu_slice, slice_is_neutrino};
469 for (
unsigned j = 0; j < n_reco_eff; j++) {
470 for (
unsigned k = 0;
k < n_reco_eff;
k++) {
471 if (pass[j] && pass[
k]) {
472 FillTrue(fReco[j * n_reco_eff + k], numucc[i], G4muons[i]);
473 FillMatchingMu(fReco[j * n_reco_eff + k], track_purity[i], track_completeness[i]);
474 FillMatchingSlc(fReco[j * n_reco_eff + k], matching_purity[i], matching_completeness[i]);
483 const std::vector<geoalgo::AABox> &boxes) {
487 if ((v0 - v1).Mag() < 1
e-6)
return 0;
500 for (
auto const &box: boxes) {
501 int n_contained = box.Contain(p0) + box.Contain(
p1);
503 if (n_contained == 2) {
504 length = (v1 - v0).Mag();
508 if (n_contained == 1) {
513 if (intersections.size() == 0) {
516 bool p0_edge = algo.
SqDist(p0, box) <
tol;
518 assert(p0_edge || p1_edge);
522 if ((p0_edge && box.Contain(p0)) || (box.Contain(
p1) && p1_edge))
525 else if ((p0_edge && box.Contain(
p1)) || (box.Contain(p0) && p1_edge)) {
526 length = (v1 - v0).Mag();
538 else if (intersections.size() == 2) {
539 length += (intersections.at(0).ToTLorentzVector().Vect() - intersections.at(1).ToTLorentzVector().Vect()).Mag();
543 else if (intersections.size() == 1) {
545 TVector3 int_tv(intersections.at(0).ToTLorentzVector().Vect());
546 length += ( box.Contain(p0) ? (v0 - int_tv).Mag() : (v1 - int_tv).Mag() );
551 if (n_contained == 0) {
553 if (!(intersections.size() == 0 || intersections.size() == 2)) {
558 bool p0_edge = algo.
SqDist(p0, box) <
tol;
561 TVector3 vint = intersections.at(0).ToTLorentzVector().Vect();
563 bool p0_int = (v0 - vint).Mag() <
tol;
564 bool p1_int = (v1 - vint).Mag() <
tol;
566 assert((p0_int && p0_edge) != (p1_int && p1_edge));
571 if (p0_edge && p1_edge) {
572 length += (v0 - v1).Mag();
578 else if (intersections.size() == 2) {
579 TVector3 start(intersections.at(0).ToTLorentzVector().Vect());
580 TVector3
end(intersections.at(1).ToTLorentzVector().Vect());
581 length += (start -
end).Mag();
592 const simb::MCParticle &genie_part,
593 const simb::MCTruth &mctruth,
598 if (genie_part.StatusCode() != 1)
return NULL;
600 const simb::MCParticle *ret = NULL;
601 for (
int iparticle = 0; iparticle < (int)g4_mcparticles.size(); iparticle++) {
602 if (infos[iparticle]->hasGeneratedParticleIndex() &&
603 (int)infos[iparticle]->generatedParticleIndex() < mctruth.NParticles() &&
604 mctruth.GetParticle(infos[iparticle]->generatedParticleIndex()).TrackId() == genie_part.TrackId() &&
605 g4_mcparticles[iparticle]->Process() ==
"primary" ) {
612 const simb::MCParticle& matched_genie_particle = mctruth.GetParticle(infos[iparticle]->generatedParticleIndex());
613 if ((matched_genie_particle.Position().Vect() - g4_mcparticles[iparticle]->Position().Vect()).Mag() < 1
e-4 &&
614 matched_genie_particle.PdgCode() == g4_mcparticles[iparticle]->PdgCode()) {
618 ret = g4_mcparticles[iparticle].get();
void FillMatchingSlc(Histos &h, float purity, float completeness)
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Algorithm to compute various geometrical relation among geometrical objects. In particular functions ...
void analyze(art::Event const &e) override
Utilities related to art service access.
double ContainedLength(const TVector3 &v0, const TVector3 &v1, const std::vector< geo::BoxBoundedGeo > &boxes)
std::vector< geo::BoxBoundedGeo > fActiveVolumes
ClusterModuleLabel join with tracks
const geo::GeometryCore * geometry
double SqDist(const Line_t &line, const Point_t &pt) const
Declaration of signal hit object.
Representation of a simple 3D line segment Defines a finite 3D straight line by having the start and ...
Geometry information for a single TPC.
void InitHisto(Histos &h, const std::string &prefix)
geo::BoxBoundedGeo const & ActiveBoundingBox() const
Returns the box of the active volume of this TPC.
std::vector< geo::BoxBoundedGeo > fFiducialVolumes
TH1D * slice_completeness
std::size_t size(FixedBins< T, C > const &) noexcept
std::array< float, 6 > fFiducialInset
std::vector< std::vector< geo::BoxBoundedGeo > > fTPCVolumes
Definition of vertex object for LArSoft.
TPC_iterator begin_TPC() const
Returns an iterator pointing to the first TPC in the detector.
std::vector< std::pair< int, float > > AllTrueParticleIDEnergyMatches(const detinfo::DetectorClocksData &clockData, const std::vector< art::Ptr< recob::Hit > > &hits, bool rollup_unsaved_ids=1)
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Access the description of detector geometry.
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
Metadata associated to PFParticles.
Ionization at a point of the TPC sensitive volume.
float ParticleLength(const simb::MCParticle &particle)
const PropertiesMap & GetPropertiesMap() const
auto end(FixedBins< T, C > const &) noexcept
void FillMatchingMu(Histos &h, float purity, float completeness)
Description of geometry of one entire detector.
Declaration of cluster object.
Provides recob::Track data product.
Provides a base class aware of world box coordinates.
void FillTrue(Histos &h, const simb::MCTruth &interaction, const simb::MCParticle &G4lepton)
IteratorBox< cryostat_iterator,&GeometryCore::begin_cryostat,&GeometryCore::end_cryostat > IterateCryostats() const
Enables ranged-for loops on all cryostats of the detector.
const simb::MCParticle * Genie2G4MCParticle(const simb::MCParticle &genie_part, const simb::MCTruth &mctruth, const std::vector< art::Ptr< simb::MCParticle >> &g4_mcparticles, const std::vector< const sim::GeneratedParticleInfo * > infos)
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
std::vector< Histos > fReco
static const unsigned n_reco_eff
art::ServiceHandle< art::TFileService > tfs
std::vector< Point_t > Intersection(const AABox_t &box, const HalfLine_t &line, bool back=false) const
Intersection between a HalfLine and an AABox.
Forward iterator browsing all geometry elements in the detector.
NuMuEfficiencyStudy & operator=(NuMuEfficiencyStudy const &)=delete
const Point_t & position() const
Return vertex 3D position.
physics associatedGroupsWithLeft p1
art framework interface to geometry description
BEGIN_PROLOG could also be cout
TPC_iterator end_TPC() const
Returns an iterator pointing after the last TPC in the detector.
NuMuEfficiencyStudy(fhicl::ParameterSet const &p)