18 #include "art/Framework/Core/EDProducer.h"
19 #include "art/Framework/Core/ModuleMacros.h"
20 #include "art/Framework/Principal/DataViewImpl.h"
21 #include "art/Framework/Principal/Event.h"
22 #include "art/Framework/Principal/Handle.h"
23 #include "art/Framework/Principal/Run.h"
24 #include "art/Framework/Principal/SubRun.h"
25 #include "art_root_io/TFileService.h"
26 #include "canvas/Persistency/Common/FindManyP.h"
27 #include "canvas/Persistency/Common/Ptr.h"
28 #include "canvas/Persistency/Common/PtrVector.h"
29 #include "canvas/Utilities/InputTag.h"
30 #include "fhiclcpp/ParameterSet.h"
32 #include "messagefacility/MessageLogger/MessageLogger.h"
59 #include "TMVA/MethodCuts.h"
60 #include "TMVA/Reader.h"
61 #include "TMVA/Tools.h"
68 class Razzle :
public art::EDProducer {
70 explicit Razzle(fhicl::ParameterSet
const&
p);
81 void produce(art::Event&
e)
override;
86 art::ServiceHandle<art::TFileService>
tfs;
121 float startX,
startY,
startZ,
endX,
endY,
endZ,
trueStartX,
trueStartY,
trueStartZ,
trueEndX,
trueEndY,
trueEndZ,
startDist,
endDist,
trueP,
energyComp,
energyPurity;
127 std::vector<art::Ptr<sim::SimChannel>>& simChannels);
129 void FillPFPMetrics(
const art::Ptr<recob::PFParticle>& pfp,
const std::map<
size_t, art::Ptr<recob::PFParticle>>& pfpMap,
130 const recob::Shower&
shower,
const art::FindManyP<larpandoraobj::PFParticleMetadata>& fmMeta,
const art::FindManyP<recob::Vertex>& fmVertex);
135 std::map<size_t, art::Ptr<recob::PFParticle>>
GetPFPMap(
std::vector<art::Ptr<recob::PFParticle>>& pfps)
const;
136 float GetPFPTrackScore(
const art::Ptr<recob::PFParticle>& pfp,
const art::FindManyP<larpandoraobj::PFParticleMetadata>& fmMeta)
const;
137 bool InFV(
const TVector3& pos)
const;
143 , fSimChannelLabel(
p.get<std::string>(
"SimChannelLabel"))
144 , fPFPLabel(
p.get<std::string>(
"PFPLabel"))
145 , fShowerLabel(
p.get<std::string>(
"ShowerLabel"))
146 , fShowerSelVarsLabel(
p.get<std::string>(
"ShowerSelVarsLabel"))
147 , fMinShowerEnergy(
p.get<
float>(
"MinShowerEnergy"))
148 , fMakeTree(
p.get<
bool>(
"MakeTree"))
149 , fRunMVA(
p.get<
bool>(
"RunMVA"))
150 , fMethodName(
p.get<std::string>(
"MethodName",
""))
151 , fWeightFile(
p.get<std::string>(
"WeightFile",
""))
152 , fXMin(
p.get<
float>(
"XMin"))
153 , fXMax(
p.get<
float>(
"XMax"))
154 , fYMin(
p.get<
float>(
"YMin"))
155 , fYMax(
p.get<
float>(
"YMax"))
156 , fZMin(
p.get<
float>(
"ZMin"))
157 , fZMax(
p.get<
float>(
"ZMax"))
159 if (!fMakeTree && !fRunMVA)
160 throw cet::exception(
"Razzle") <<
"Configured to do nothing";
163 if (fMethodName ==
"" || fWeightFile ==
"")
164 throw cet::exception(
"Razzle") <<
"Trying to run MVA with inputs not set: MethodName: " << fMethodName <<
" and WeightFile: " << fWeightFile;
166 cet::search_path searchPath(
"FW_SEARCH_PATH");
167 std::string fWeightFileFullPath;
168 if (!searchPath.find_file(fWeightFile, fWeightFileFullPath))
169 throw cet::exception(
"Razzle") <<
"Unable to find weight file: " << fWeightFile <<
" in FW_SEARCH_PATH: " << searchPath.to_string();
171 reader =
new TMVA::Reader(
"V");
174 reader->AddVariable(
"bestdEdx", &bestdEdx);
175 reader->AddVariable(
"convGap", &convGap);
176 reader->AddVariable(
"openAngle", &openAngle);
177 reader->AddVariable(
"modHitDensity", &modHitDensity);
179 reader->AddVariable(
"sqrtEnergyDensity", &sqrtEnergyDensity);
181 reader->BookMVA(fMethodName, fWeightFileFullPath);
184 produces<std::vector<MVAPID>>();
185 produces<art::Assns<recob::Shower, MVAPID>>();
191 showerTree =
tfs->make<TTree>(
"showerTree",
"Tree filled per Shower with PID variables");
257 auto const clockData(art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(e));
259 auto const pfpHandle(e.getValidHandle<std::vector<recob::PFParticle>>(
fPFPLabel));
260 auto const simChannelHandle(e.getValidHandle<std::vector<sim::SimChannel>>(
fSimChannelLabel));
261 auto const showerHandle(e.getValidHandle<std::vector<recob::Shower>>(
fShowerLabel));
263 std::vector<art::Ptr<recob::PFParticle>> pfps;
264 art::fill_ptr_vector(pfps, pfpHandle);
266 std::vector<art::Ptr<sim::SimChannel>> simChannels;
267 art::fill_ptr_vector(simChannels, simChannelHandle);
269 art::FindManyP<recob::Vertex> fmPFPVertex(pfpHandle, e,
fPFPLabel);
270 art::FindManyP<larpandoraobj::PFParticleMetadata> fmPFPMeta(pfpHandle, e,
fPFPLabel);
272 art::FindManyP<recob::Shower> fmPFPShower(pfpHandle, e,
fShowerLabel);
273 art::FindManyP<recob::Hit> fmShowerHit(showerHandle, e,
fShowerLabel);
278 auto mvaPIDVec = std::make_unique<std::vector<MVAPID>>();
279 auto showerAssns = std::make_unique<art::Assns<recob::Shower, MVAPID>>();
281 const std::map<size_t, art::Ptr<recob::PFParticle>> pfpMap(this->
GetPFPMap(pfps));
283 for (
auto const& pfp : pfps) {
287 std::vector<art::Ptr<recob::Shower>> pfpShowerVec(fmPFPShower.at(pfp.key()));
290 if (pfpShowerVec.empty())
294 if (pfpShowerVec.size() > 1)
295 throw cet::exception(
"Razzle") <<
"Too many showers: " << pfpShowerVec.size();
297 art::Ptr<recob::Shower>& pfpShower(pfpShowerVec.front());
299 if (pfpShower->best_plane() < 0 || pfpShower->Energy().at(pfpShower->best_plane()) <
fMinShowerEnergy)
302 std::vector<art::Ptr<recob::Hit>> showerHitVec(fmShowerHit.at(pfpShower.key()));
306 this->
FillPFPMetrics(pfp, pfpMap, *pfpShower, fmPFPMeta, fmPFPVertex);
308 auto const densityFitVec(fmShowerDensityFit.at(pfpShower.key()));
309 if (densityFitVec.size() == 1)
312 auto const trackFitVec(fmShowerTrackFit.at(pfpShower.key()));
313 if (trackFitVec.size() == 1)
318 mvaPIDVec->push_back(mvaPID);
328 e.put(std::move(mvaPIDVec));
329 e.put(std::move(showerAssns));
393 art::ServiceHandle<cheat::BackTrackerService> bt_serv;
399 float totalHitEnergy(0.f), totalTrueHitEnergy(0.f);
400 for (
auto const&
hit : hits) {
401 const std::vector<sim::TrackIDE> trackIDEs(bt_serv->HitToTrackIDEs(clockData,
hit));
402 totalHitEnergy = std::accumulate(trackIDEs.cbegin(), trackIDEs.cend(), totalHitEnergy,
403 [](
float sum,
auto const& ide) {
return sum + ide.energy; });
404 totalTrueHitEnergy = std::accumulate(trackIDEs.cbegin(), trackIDEs.cend(), totalTrueHitEnergy,
405 [bestMatch](
float sum,
auto const& ide) {
return (
std::abs(ide.trackID) == bestMatch) ? sum + ide.energy : sum; });
408 const std::vector<const sim::IDE*> trackIDEs(bt_serv->TrackIdToSimIDEs_Ps(bestMatch));
409 float totalTrueEnergy(std::accumulate(trackIDEs.cbegin(), trackIDEs.cend(), 0.f,
410 [](
float sum,
auto const& ide) {
return sum + ide->energy; }));
412 energyComp = totalTrueHitEnergy / totalTrueEnergy;
415 const simb::MCParticle*
const trueParticle(
particleInventory->TrackIdToParticle_P(bestMatch));
420 truePdg = trueParticle->PdgCode();
424 trueP = trueParticle->P();
427 const TVector3 showerEnd(showerStart + shower.
Length() * shower.
Direction());
430 TVector3 PositionTrajStart(trueParticle->Position(0).Vect());
433 if (trueParticle->PdgCode() == 22) {
434 unsigned int trajPoint(1);
435 while (trueParticle->E(trajPoint) == trueParticle->E()) {
438 PositionTrajStart = trueParticle->Position(trajPoint).Vect();
441 const TVector3 trueStart(PositionTrajStart);
442 const TVector3 trueEnd(trueParticle->EndPosition().Vect());
452 startDist = (trueStart - showerStart).Mag();
453 endDist = (trueEnd - showerEnd).Mag();
464 const TVector3
end(start + length * shower.
Direction());
469 std::array<int, 3> showerPlaneHits { 0, 0, 0 };
470 for (
auto const&
hit : hitVec) {
471 showerPlaneHits[
hit->WireID().Plane]++;
474 std::array<float, 3> showerPlanePitches { -1.f, -1.f, -1.f };
478 const float cosgamma(
std::abs(std::sin(angleToVert) * shower.
Direction().Y() + std::cos(angleToVert) * shower.
Direction().Z()));
480 showerPlanePitches[plane.ID().Plane] = plane.WirePitch() / cosgamma;
487 if (bestPlane < 0 || bestPlane > 3)
488 throw cet::exception(
"Razzle") <<
"Best plane: " <<
bestPlane;
501 const float wiresHit(
bestPitch > std::numeric_limits<float>::epsilon() ? length /
bestPitch : -5.f);
522 void Razzle::FillPFPMetrics(
const art::Ptr<recob::PFParticle>& pfp,
const std::map<
size_t, art::Ptr<recob::PFParticle>>& pfpMap,
523 const recob::Shower&
shower,
const art::FindManyP<larpandoraobj::PFParticleMetadata>& fmMeta,
const art::FindManyP<recob::Vertex>& fmVertex)
528 auto const parentId(pfp->Parent());
529 auto const& parentIter(pfpMap.find(parentId));
531 if (parentIter == pfpMap.end())
536 auto const& parentVertexVec = fmVertex.at(parentIter->second.key());
538 if (parentVertexVec.empty())
542 const auto parentVertexPoint(parentVertexVec.front()->position());
543 const TVector3 parentVertex { parentVertexPoint.X(), parentVertexPoint.Y(), parentVertexPoint.Z() };
567 pidResults.AddScore(11, mvaScores.at(0));
568 pidResults.AddScore(22, mvaScores.at(1));
569 pidResults.AddScore(0, mvaScores.at(2));
579 bestPDG = pidResults.BestPDG();
586 std::map<size_t, art::Ptr<recob::PFParticle>> pfpMap;
587 for (
auto const& pfp : pfps) {
588 pfpMap[pfp->Self()] = pfp;
593 float Razzle::GetPFPTrackScore(
const art::Ptr<recob::PFParticle>& pfp,
const art::FindManyP<larpandoraobj::PFParticleMetadata>& fmMeta)
const
595 auto const pfpMetaVec(fmMeta.at(pfp.key()));
596 if (pfpMetaVec.size() != 1)
599 auto const& pfpTrackScoreIter = propertiesMap.find(
"TrackScore");
600 return pfpTrackScoreIter == propertiesMap.end() ? -5.f : pfpTrackScoreIter->second;
Utilities related to art service access.
IteratorBox< plane_iterator,&GeometryCore::begin_plane,&GeometryCore::end_plane > IteratePlanes() const
Enables ranged-for loops on all planes of the detector.
art::InputTag fSimChannelLabel
const TVector3 & Direction() const
Declaration of signal hit object.
const std::vector< double > & dEdx() const
bool InFV(const TVector3 &pos) const
std::map< std::string, float > PropertiesMap
const std::string fWeightFile
void FillTrueParticleMetrics(const detinfo::DetectorClocksData &clockData, const recob::Shower &shower, const std::vector< art::Ptr< recob::Hit >> &hits, std::vector< art::Ptr< sim::SimChannel >> &simChannels)
void FillTrackFitMetrics(const ShowerTrackFit &trackFit)
art::InputTag fShowerLabel
art::InputTag fShowerSelVarsLabel
void FillShowerMetrics(const recob::Shower &shower, const std::vector< art::Ptr< recob::Hit >> &hitVec)
const std::string fMethodName
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Razzle(fhicl::ParameterSet const &p)
Utilities for matching a recob::Hit or vector of recob::Hit to the ID of the most significantly contr...
std::string trueEndProcess
art::ServiceHandle< cheat::ParticleInventoryService > particleInventory
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
auto end(FixedBins< T, C > const &) noexcept
std::string PdgString(const int pdg) const
Description of geometry of one entire detector.
bool Valid(const G4ID g4ID) noexcept
Test whether a G4ID returned by the TruthMatchUtils functions is valid.
bool CreateAssn(art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t index=UINT_MAX)
Creates a single one-to-one association.
std::map< size_t, art::Ptr< recob::PFParticle > > GetPFPMap(std::vector< art::Ptr< recob::PFParticle >> &pfps) const
void FillDensityFitMetrics(const ShowerDensityFit &densityFit)
const float fMinShowerEnergy
void FillPFPMetrics(const art::Ptr< recob::PFParticle > &pfp, const std::map< size_t, art::Ptr< recob::PFParticle >> &pfpMap, const recob::Shower &shower, const art::FindManyP< larpandoraobj::PFParticleMetadata > &fmMeta, const art::FindManyP< recob::Vertex > &fmVertex)
Contains all timing reference information for the detector.
Razzle & operator=(Razzle const &)=delete
void produce(art::Event &e) override
G4ID TrueParticleIDFromTotalTrueEnergy(detinfo::DetectorClocksData const &clockData, const std::vector< art::Ptr< recob::Hit >> &pHits, const bool rollupUnsavedIDs)
The G4 ID of the true particle which deposits the most energy in a vector of recob::Hit.
const std::vector< double > & Energy() const
const TVector3 & ShowerStart() const
art::ServiceHandle< art::TFileService > tfs
float GetPFPTrackScore(const art::Ptr< recob::PFParticle > &pfp, const art::FindManyP< larpandoraobj::PFParticleMetadata > &fmMeta) const
double WireAngleToVertical(geo::View_t view, geo::TPCID const &tpcid) const
Returns the angle of the wires in the specified view from vertical.
art framework interface to geometry description