15 #include "art/Framework/Core/EDProducer.h"
16 #include "art/Framework/Core/ModuleMacros.h"
17 #include "art/Framework/Principal/Event.h"
18 #include "art/Framework/Principal/Handle.h"
19 #include "art/Framework/Services/Registry/ServiceHandle.h"
20 #include "art/Persistency/Common/PtrMaker.h"
21 #include "canvas/Persistency/Common/FindManyP.h"
22 #include "canvas/Persistency/Common/Ptr.h"
23 #include "canvas/Persistency/Common/PtrVector.h"
24 #include "cetlib/pow.h"
25 #include "fhiclcpp/ParameterSet.h"
26 #include "messagefacility/MessageLogger/MessageLogger.h"
44 #include "RtypesCore.h"
59 #include "range/v3/view.hpp"
62 template <
typename T,
typename U>
64 AddMany(art::Ptr<T>
const& ptr, art::Assns<T, U>& assns) : ptr_{ptr}, assns_{assns} {}
67 operator()(art::Ptr<U>
const& b)
const
69 assns_.addSingle(ptr_, b);
72 art::Ptr<T>
const ptr_;
73 art::Assns<T, U>& assns_;
85 EMShower(fhicl::ParameterSet
const& pset);
107 art::ServiceHandle<geo::Geometry const>
fGeom;
112 , fHitsModuleLabel{pset.get<art::InputTag>(
"HitsModuleLabel")}
113 , fClusterModuleLabel{pset.get<art::InputTag>(
"ClusterModuleLabel")}
114 , fTrackModuleLabel{pset.get<art::InputTag>(
"TrackModuleLabel")}
115 , fPFParticleModuleLabel{pset.get<art::InputTag>(
"PFParticleModuleLabel",
"")}
116 , fVertexModuleLabel{pset.get<art::InputTag>(
"VertexModuleLabel",
"")}
117 , fCNNEMModuleLabel{pset.get<art::InputTag>(
"CNNEMModuleLabel",
"")}
118 , fShower{pset.get<
int>(
"Shower", -1)}
119 , fPlane{pset.get<
int>(
"Plane", -1)}
120 , fDebug{pset.get<
int>(
"Debug", 0)}
121 , fEMShowerAlg{pset.get<fhicl::ParameterSet>(
"EMShowerAlg"), fDebug}
122 , fSaveNonCompleteShowers{pset.get<
bool>(
"SaveNonCompleteShowers")}
123 , fFindBadPlanes{pset.get<
bool>(
"FindBadPlanes")}
124 , fMakeSpacePoints{pset.get<
bool>(
"MakeSpacePoints")}
125 , fUseCNNtoIDEMPFP{pset.get<
bool>(
"UseCNNtoIDEMPFP")}
126 , fUseCNNtoIDEMHit{pset.get<
bool>(
"UseCNNtoIDEMHit")}
127 , fMinTrackLikeScore{pset.get<
double>(
"MinTrackLikeScore")}
129 produces<std::vector<recob::Shower>>();
130 produces<std::vector<recob::SpacePoint>>();
131 produces<art::Assns<recob::Shower, recob::Hit>>();
132 produces<art::Assns<recob::Shower, recob::Cluster>>();
133 produces<art::Assns<recob::Shower, recob::Track>>();
134 produces<art::Assns<recob::Shower, recob::SpacePoint>>();
135 produces<art::Assns<recob::SpacePoint, recob::Hit>>();
142 auto showers = std::make_unique<std::vector<recob::Shower>>();
143 auto spacePoints = std::make_unique<std::vector<recob::SpacePoint>>();
144 auto clusterAssociations = std::make_unique<art::Assns<recob::Shower, recob::Cluster>>();
145 auto hitShowerAssociations = std::make_unique<art::Assns<recob::Shower, recob::Hit>>();
146 auto trackAssociations = std::make_unique<art::Assns<recob::Shower, recob::Track>>();
147 auto spShowerAssociations = std::make_unique<art::Assns<recob::Shower, recob::SpacePoint>>();
148 auto hitSpAssociations = std::make_unique<art::Assns<recob::SpacePoint, recob::Hit>>();
153 art::Handle<std::vector<recob::Hit>> hitHandle;
154 std::vector<art::Ptr<recob::Hit>> hits;
155 if (evt.getByLabel(fHitsModuleLabel, hitHandle)) art::fill_ptr_vector(hits, hitHandle);
158 art::Handle<std::vector<recob::Track>> trackHandle;
159 std::vector<art::Ptr<recob::Track>>
tracks;
160 if (evt.getByLabel(fTrackModuleLabel, trackHandle)) art::fill_ptr_vector(tracks, trackHandle);
163 art::Handle<std::vector<recob::Cluster>> clusterHandle;
164 std::vector<art::Ptr<recob::Cluster>> clusters;
165 if (evt.getByLabel(fClusterModuleLabel, clusterHandle))
166 art::fill_ptr_vector(clusters, clusterHandle);
169 art::Handle<std::vector<recob::PFParticle>> pfpHandle;
170 std::vector<art::Ptr<recob::PFParticle>> pfps;
171 if (evt.getByLabel(fPFParticleModuleLabel, pfpHandle)) art::fill_ptr_vector(pfps, pfpHandle);
174 art::Handle<std::vector<recob::Vertex>> vtxHandle;
175 std::vector<art::Ptr<recob::Vertex>> vertices;
176 if (evt.getByLabel(fVertexModuleLabel, vtxHandle)) art::fill_ptr_vector(vertices, vtxHandle);
179 art::FindManyP<recob::Hit> fmh(clusterHandle, evt, fClusterModuleLabel);
180 art::FindManyP<recob::Track> fmt(hitHandle, evt, fTrackModuleLabel);
181 art::FindManyP<recob::SpacePoint> fmsp(trackHandle, evt, fTrackModuleLabel);
182 art::FindManyP<recob::Cluster> fmc(hitHandle, evt, fHitsModuleLabel);
185 auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
187 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clockData);
188 std::vector<std::vector<int>> newShowers;
189 std::vector<unsigned int> pfParticles;
191 std::map<int, std::vector<int>> clusterToTracks;
192 std::map<int, std::vector<int>> trackToClusters;
194 if (!pfpHandle.isValid()) {
197 fEMShowerAlg.AssociateClustersAndTracks(clusters, fmh, fmt, clusterToTracks, trackToClusters);
200 std::vector<std::vector<int>> initialShowers = fEMShowerAlg.FindShowers(trackToClusters);
203 std::vector<int> clustersToIgnore;
205 clustersToIgnore = fEMShowerAlg.CheckShowerPlanes(initialShowers, clusters, fmh);
207 if (clustersToIgnore.size() > 0) {
208 clusterToTracks.clear();
209 trackToClusters.clear();
210 fEMShowerAlg.AssociateClustersAndTracks(
211 clusters, fmh, fmt, clustersToIgnore, clusterToTracks, trackToClusters);
212 newShowers = fEMShowerAlg.FindShowers(trackToClusters);
215 newShowers = initialShowers;
221 art::FindManyP<recob::Cluster> fmcp(pfpHandle, evt, fPFParticleModuleLabel);
222 for (
size_t ipfp = 0; ipfp < pfps.size(); ++ipfp) {
223 art::Ptr<recob::PFParticle> pfp = pfps[ipfp];
224 if (fCNNEMModuleLabel !=
"" && fUseCNNtoIDEMPFP) {
227 throw cet::exception(
"EMShower") <<
"Cannot get MVA results from " << fCNNEMModuleLabel;
229 int trkLikeIdx = hitResults->getIndex(
"track");
230 int emLikeIdx = hitResults->getIndex(
"em");
231 if ((trkLikeIdx < 0) || (emLikeIdx < 0)) {
232 throw cet::exception(
"EMShower") <<
"No em/track labeled columns in MVA data products.";
234 if (fmcp.isValid()) {
235 std::vector<art::Ptr<recob::Hit>> pfphits;
236 std::vector<art::Ptr<recob::Cluster>> clus = fmcp.at(ipfp);
237 for (
size_t iclu = 0; iclu < clus.size(); ++iclu) {
238 std::vector<art::Ptr<recob::Hit>> ClusterHits = fmh.at(clus[iclu].key());
239 pfphits.insert(pfphits.end(), ClusterHits.begin(), ClusterHits.end());
241 if (pfphits.size()) {
242 auto vout = hitResults->getOutput(pfphits);
243 double trk_like = -1, trk_or_em = vout[trkLikeIdx] + vout[emLikeIdx];
245 trk_like = vout[trkLikeIdx] / trk_or_em;
246 if (trk_like < fMinTrackLikeScore) {
247 std::vector<int> clusters;
248 for (
size_t iclu = 0; iclu < clus.size(); ++iclu) {
249 clusters.push_back(clus[iclu].key());
251 if (clusters.size()) {
252 newShowers.push_back(clusters);
253 pfParticles.push_back(ipfp);
260 throw cet::exception(
"EMShower") <<
"Cannot get associated cluster for PFParticle "
261 << fPFParticleModuleLabel.encode() <<
"[" << ipfp <<
"]";
264 else if (pfp->PdgCode() == 11) {
265 if (fmcp.isValid()) {
266 std::vector<int> clusters;
267 std::vector<art::Ptr<recob::Cluster>> clus = fmcp.at(ipfp);
268 for (
size_t iclu = 0; iclu < clus.size(); ++iclu) {
269 clusters.push_back(clus[iclu].key());
271 if (clusters.size()) {
272 newShowers.push_back(clusters);
273 pfParticles.push_back(ipfp);
282 for (
auto const& newShower : newShowers) {
284 if (showerNum != fShower
and fShower != -1)
continue;
287 if (fDebug > 0)
std::cout <<
"\n\nStart shower " << showerNum <<
'\n';
290 art::PtrVector<recob::Hit> showerHits;
291 art::PtrVector<recob::Cluster> showerClusters;
292 art::PtrVector<recob::Track> showerTracks;
293 art::PtrVector<recob::SpacePoint> showerSpacePoints_p;
295 std::vector<int> associatedTracks;
298 for (
int const showerCluster : newShower) {
301 art::Ptr<recob::Cluster>
const cluster = clusters.at(showerCluster);
302 showerClusters.push_back(cluster);
305 std::vector<art::Ptr<recob::Hit>>
const& showerClusterHits = fmh.at(cluster.key());
306 if (fCNNEMModuleLabel !=
"" && fUseCNNtoIDEMHit) {
309 throw cet::exception(
"EMShower")
310 <<
"Cannot get MVA results from " << fCNNEMModuleLabel.encode();
312 int trkLikeIdx = hitResults->getIndex(
"track");
313 int emLikeIdx = hitResults->getIndex(
"em");
314 if (trkLikeIdx < 0 || emLikeIdx < 0) {
315 throw cet::exception(
"EMShower") <<
"No em/track labeled columns in MVA data products.";
317 for (
auto const& showerHit : showerClusterHits) {
318 auto vout = hitResults->getOutput(showerHit);
319 double trk_like = -1, trk_or_em = vout[trkLikeIdx] + vout[emLikeIdx];
321 trk_like = vout[trkLikeIdx] / trk_or_em;
322 if (trk_like < fMinTrackLikeScore) {
323 showerHits.push_back(showerHit);
329 for (
auto const& showerClusterHit : showerClusterHits)
330 showerHits.push_back(showerClusterHit);
333 if (!pfpHandle.isValid()) {
334 for (
int const clusterTrack : clusterToTracks.at(showerCluster))
335 if (not cet::search_all(associatedTracks, clusterTrack))
336 associatedTracks.push_back(clusterTrack);
340 if (!pfpHandle.isValid()) {
342 for (
int const trackIndex : associatedTracks) {
343 showerTracks.push_back(tracks.at(trackIndex));
347 art::FindManyP<recob::SpacePoint> fmspp(showerHits, evt, fPFParticleModuleLabel);
348 if (fmspp.isValid()) {
349 for (
size_t ihit = 0; ihit < showerHits.size(); ++ihit) {
350 for (
auto const& spPtr : fmspp.at(ihit))
351 showerSpacePoints_p.push_back(spPtr);
356 if (!pfpHandle.isValid()) {
360 std::cout <<
" ------------------ Ordering shower hits --------------------\n";
361 std::map<int, std::vector<art::Ptr<recob::Hit>>> showerHitsMap =
362 fEMShowerAlg.OrderShowerHits(
detProp, showerHits, fPlane);
364 std::cout <<
" ------------------ End ordering shower hits "
365 "--------------------\n";
368 std::unique_ptr<recob::Track> initialTrack;
369 std::map<int, std::vector<art::Ptr<recob::Hit>>> initialTrackHits;
370 fEMShowerAlg.FindInitialTrack(
detProp, showerHitsMap, initialTrack, initialTrackHits, fPlane);
373 std::vector<std::vector<art::Ptr<recob::Hit>>> hitAssns;
374 std::vector<recob::SpacePoint> showerSpacePoints;
375 if (fMakeSpacePoints)
376 showerSpacePoints = fEMShowerAlg.MakeSpacePoints(
detProp, showerHitsMap, hitAssns);
378 for (
auto const& trkPtr : showerTracks) {
379 for (
auto const& trackSpacePoint :
381 showerSpacePoints.push_back(trackSpacePoint);
382 hitAssns.push_back(
std::vector<art::Ptr<recob::Hit>>());
388 art::PtrMaker<recob::SpacePoint>
const make_space_point_ptr{evt};
389 size_t firstSpacePoint = spacePoints->size(), nSpacePoint = 0;
390 for (
auto const& ssp : showerSpacePoints) {
391 spacePoints->emplace_back(ssp.XYZ(), ssp.ErrXYZ(), ssp.Chisq(), spacePoints->size());
392 auto const index = spacePoints->size() - 1;
393 auto const space_point_ptr = make_space_point_ptr(index);
394 cet::for_all(hitAssns.at(nSpacePoint), AddMany{space_point_ptr, *hitSpAssociations});
396 auto const lastSpacePoint = spacePoints->size();
400 fEMShowerAlg.MakeShower(clockData,
detProp, showerHits, initialTrack, initialTrackHits);
402 if (fSaveNonCompleteShowers or
403 (!fSaveNonCompleteShowers
and shower.
ShowerStart() != TVector3{})) {
404 showers->push_back(shower);
406 auto const shower_ptr = art::PtrMaker<recob::Shower>{evt}(showers->size() - 1);
407 cet::for_all(showerHits, AddMany{shower_ptr, *hitShowerAssociations});
408 cet::for_all(showerClusters, AddMany{shower_ptr, *clusterAssociations});
409 cet::for_all(showerTracks, AddMany{shower_ptr, *trackAssociations});
410 for (
size_t i = firstSpacePoint; i < lastSpacePoint; ++i) {
411 spShowerAssociations->addSingle(shower_ptr, make_space_point_ptr(i));
415 mf::LogInfo(
"EMShower") <<
"Discarding shower " << showerNum
416 <<
" due to incompleteness (SaveNonCompleteShowers == false)";
421 if (vertices.size()) {
425 for (
auto const& vtx : vertices) {
426 auto const pos = vtx->position();
427 if (pos.Z() < nuvtx.Z()) { nuvtx = pos; }
431 double mindist2 = DBL_MAX;
433 double const dist2 = cet::sum_of_squares(
434 nuvtx.X() - sp.XYZ()[0], nuvtx.Y() - sp.XYZ()[1], nuvtx.Z() - sp.XYZ()[2]);
435 if (dist2 < mindist2) {
437 shwvtx.SetXYZ(sp.XYZ()[0], sp.XYZ()[1], sp.XYZ()[2]);
441 art::Ptr<recob::Vertex> bestvtx;
443 for (
auto const& vtx : vertices) {
444 auto const pos = vtx->position();
446 cet::sum_of_squares(pos.X() - shwvtx.X(), pos.Y() - shwvtx.Y(), pos.Z() - shwvtx.Z());
447 if (dist2 < mindist2) {
455 fEMShowerAlg.MakeShower(clockData,
detProp, showerHits, bestvtx, iok);
457 showers->push_back(shower);
458 auto const index = showers->size() - 1;
459 showers->back().set_id(index);
461 auto const shower_ptr = art::PtrMaker<recob::Shower>{evt}(index);
462 cet::for_all(showerHits, AddMany{shower_ptr, *hitShowerAssociations});
463 cet::for_all(showerClusters, AddMany{shower_ptr, *clusterAssociations});
464 cet::for_all(showerTracks, AddMany{shower_ptr, *trackAssociations});
465 cet::for_all(showerSpacePoints_p, AddMany{shower_ptr, *spShowerAssociations});
472 evt.put(std::move(showers));
473 evt.put(std::move(spacePoints));
474 evt.put(std::move(hitShowerAssociations));
475 evt.put(std::move(clusterAssociations));
476 evt.put(std::move(trackAssociations));
477 evt.put(std::move(spShowerAssociations));
478 evt.put(std::move(hitSpAssociations));
bool const fUseCNNtoIDEMPFP
Utilities related to art service access.
constexpr to_element_t to_element
ClusterModuleLabel join with tracks
art::InputTag const fVertexModuleLabel
art::InputTag const fClusterModuleLabel
Declaration of signal hit object.
bool const fMakeSpacePoints
EMShower(fhicl::ParameterSet const &pset)
bool const fUseCNNtoIDEMHit
art::InputTag const fTrackModuleLabel
bool const fFindBadPlanes
recob::tracking::Point_t Point_t
art::InputTag const fPFParticleModuleLabel
void set_id(const int id)
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
art::InputTag const fHitsModuleLabel
return match has_match and(match.match_pdg==11 or match.match_pdg==-11)
double const fMinTrackLikeScore
Declaration of cluster object.
Provides recob::Track data product.
void produce(art::Event &evt)
EMShowerAlg const fEMShowerAlg
const TVector3 & ShowerStart() const
art::InputTag const fCNNEMModuleLabel
bool const fSaveNonCompleteShowers
art::ServiceHandle< geo::Geometry const > fGeom
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< Coord_t >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space. See recob::tracking::Coord_t for more detai...
static std::unique_ptr< MVAReader > create(const art::Event &evt, const art::InputTag &tag)
art framework interface to geometry description
BEGIN_PROLOG could also be cout