33 #include "art/Framework/Core/EDProducer.h"
34 #include "art/Framework/Core/ModuleMacros.h"
35 #include "art/Framework/Principal/Event.h"
36 #include "art/Framework/Principal/Handle.h"
37 #include "art/Persistency/Common/PtrMaker.h"
38 #include "art_root_io/TFileService.h"
39 #include "canvas/Utilities/InputTag.h"
40 #include "fhiclcpp/types/Atom.h"
41 #include "fhiclcpp/types/Table.h"
42 #include "messagefacility/MessageLogger/MessageLogger.h"
78 Name(
"ProjectionMatchingAlg")};
89 Name(
"SaveOnlyBranchingVtx"),
90 Comment(
"use true to save only vertices interconnecting many tracks, otherwise vertex is "
91 "added to the front of each track")};
95 Comment(
"save track nodes (only for algorithm development purposes)")};
98 Name(
"HitModuleLabel"),
99 Comment(
"tag of unclustered hits, which were used to validate tracks")};
102 Comment(
"tag of recob::Wire producer.")};
105 Name(
"ClusterModuleLabel"),
106 Comment(
"tag of cluster collection, these clusters are used for track building")};
109 Name(
"EmClusterModuleLabel"),
110 Comment(
"EM-like clusters, will be excluded from tracking if provided")};
122 void produce(art::Event&
e)
override;
169 , fHitModuleLabel(config().HitModuleLabel())
171 , fCluModuleLabel(config().ClusterModuleLabel())
172 , fEmModuleLabel(config().EmClusterModuleLabel())
173 , fPmaConfig(config().ProjectionMatchingAlg())
174 , fPmaTrackerConfig(config().PMAlgTracking())
175 , fPmaTaggingConfig(config().PMAlgCosmicTagging())
176 , fPmaVtxConfig(config().PMAlgVertexing())
177 , fPmaStitchConfig(config().PMAlgStitching())
178 , fSaveOnlyBranchingVtx(config().SaveOnlyBranchingVtx())
179 , fSavePmaNodes(config().SavePmaNodes())
180 ,
fGeom(art::ServiceHandle<geo::Geometry const>().
get())
182 produces<std::vector<recob::Track>>();
183 produces<std::vector<recob::SpacePoint>>();
184 produces<std::vector<recob::Vertex>>();
185 produces<std::vector<recob::Vertex>>(kKinksName);
186 produces<std::vector<recob::Vertex>>(kNodesName);
187 produces<std::vector<anab::T0>>();
188 produces<std::vector<anab::CosmicTag>>();
192 produces<art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta>>();
194 produces<art::Assns<recob::Track, recob::SpacePoint>>();
195 produces<art::Assns<recob::SpacePoint, recob::Hit>>();
199 produces<art::Assns<recob::Track, recob::Vertex>>(kKinksName);
200 produces<art::Assns<recob::Track, anab::T0>>();
201 produces<art::Assns<recob::Track, anab::CosmicTag>>();
203 produces<std::vector<recob::PFParticle>>();
204 produces<art::Assns<recob::PFParticle, recob::Cluster>>();
205 produces<art::Assns<recob::PFParticle, recob::Vertex>>();
206 produces<art::Assns<recob::PFParticle, recob::Track>>();
208 if (fPmaTrackerConfig.Validation() ==
"calib")
210 art::ServiceHandle<art::TFileService const>
tfs;
211 for (
size_t p = 0;
p <
fGeom->MaxPlanes(); ++
p) {
212 std::ostringstream ss1;
213 ss1 <<
"adc_plane_" <<
p;
214 fAdcInPassingPoints.push_back(tfs->make<TH1F>(
215 (ss1.str() +
"_passing").c_str(),
"max adc around the point on track", 100., 0., 5.));
216 fAdcInRejectedPoints.push_back(tfs->make<TH1F>(
217 (ss1.str() +
"_rejected").c_str(),
"max adc around spurious point ", 100., 0., 5.));
231 int trkLikeIdx = hitResults->getIndex(
"track");
232 int emLikeIdx = hitResults->getIndex(
"em");
233 if ((trkLikeIdx < 0) || (emLikeIdx < 0)) {
234 throw cet::exception(
"PMAlgTrackMaker")
235 <<
"No em/track labeled columns in MVA data products." << std::endl;
238 size_t nh[3] = {0, 0, 0};
239 for (
size_t hidx = 0; hidx < trk.
size(); ++hidx) {
240 ++nh[trk[hidx]->View2D()];
243 size_t best_view = 2;
244 if ((nh[0] >= nh[1]) && (nh[0] > 1.25 * nh[2])) best_view = 0;
245 if ((nh[1] >= nh[0]) && (nh[1] > 1.25 * nh[2])) best_view = 1;
247 std::vector<art::Ptr<recob::Hit>> trkHitPtrList;
248 trkHitPtrList.reserve(nh[best_view]);
249 for (
size_t hidx = 0; hidx < trk.
size(); ++hidx) {
250 if (trk[hidx]->View2D() == best_view) {
251 trkHitPtrList.emplace_back(trk[hidx]->Hit2DPtr());
254 auto vout = hitResults->getOutput(trkHitPtrList);
255 double trk_like = -1, trk_or_em = vout[trkLikeIdx] + vout[emLikeIdx];
257 trk_like = vout[trkLikeIdx] / trk_or_em;
272 if (!cluResults) {
return false; }
274 int trkLikeIdx = cluResults->getIndex(
"track");
275 int emLikeIdx = cluResults->getIndex(
"em");
276 if ((trkLikeIdx < 0) || (emLikeIdx < 0)) {
return false; }
278 const art::FindManyP<recob::Hit> hitsFromClusters(
279 cluResults->dataHandle(),
evt, cluResults->dataTag());
280 const auto& cnnOuts = cluResults->outputs();
281 std::vector<float> trackLike(cnnOuts.size());
282 for (
size_t i = 0; i < cnnOuts.size(); ++i) {
283 double trkOrEm = cnnOuts[i][trkLikeIdx] + cnnOuts[i][emLikeIdx];
284 if (trkOrEm > 0) { trackLike[i] = cnnOuts[i][trkLikeIdx] / trkOrEm; }
289 pmalgTracker.
init(hitsFromClusters, trackLike);
293 std::vector<anab::CosmicTagID_t>
296 std::vector<anab::CosmicTagID_t> anabTags;
323 if (anabTags.empty()) { anabTags.push_back(anab::CosmicTagID_t::kUnknown); }
332 auto tracks = std::make_unique<std::vector<recob::Track>>();
333 auto allsp = std::make_unique<std::vector<recob::SpacePoint>>();
334 auto vtxs = std::make_unique<std::vector<recob::Vertex>>();
335 auto kinks = std::make_unique<
336 std::vector<recob::Vertex>>();
337 auto nodes = std::make_unique<std::vector<recob::Vertex>>();
338 auto t0s = std::make_unique<std::vector<anab::T0>>();
339 auto cosmicTags = std::make_unique<std::vector<anab::CosmicTag>>();
341 auto trk2hit_oldway = std::make_unique<
344 auto trk2hit = std::make_unique<art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta>>();
346 auto trk2sp = std::make_unique<art::Assns<recob::Track, recob::SpacePoint>>();
347 auto trk2t0 = std::make_unique<art::Assns<recob::Track, anab::T0>>();
348 auto trk2ct = std::make_unique<art::Assns<recob::Track, anab::CosmicTag>>();
350 auto sp2hit = std::make_unique<art::Assns<recob::SpacePoint, recob::Hit>>();
351 auto vtx2trk = std::make_unique<
352 art::Assns<recob::Vertex,
355 std::make_unique<art::Assns<recob::Track, recob::Vertex>>();
357 auto pfps = std::make_unique<std::vector<recob::PFParticle>>();
359 auto pfp2clu = std::make_unique<art::Assns<recob::PFParticle, recob::Cluster>>();
360 auto pfp2vtx = std::make_unique<art::Assns<recob::PFParticle, recob::Vertex>>();
361 auto pfp2trk = std::make_unique<art::Assns<recob::PFParticle, recob::Track>>();
364 auto wireHandle = evt.getValidHandle<std::vector<recob::Wire>>(
fWireModuleLabel);
365 auto allHitListHandle = evt.getValidHandle<std::vector<recob::Hit>>(
fHitModuleLabel);
366 std::vector<art::Ptr<recob::Hit>> allhitlist;
367 art::fill_ptr_vector(allhitlist, allHitListHandle);
380 size_t mvaLength = 0;
383 auto cluListHandle = evt.getValidHandle<std::vector<recob::Cluster>>(
fCluModuleLabel);
384 auto splitCluHandle = evt.getValidHandle<std::vector<recob::Cluster>>(
fEmModuleLabel);
386 art::FindManyP<recob::Hit> hitsFromClusters(cluListHandle, evt,
fCluModuleLabel);
387 art::FindManyP<recob::Hit> hitsFromEmParts(splitCluHandle, evt,
fEmModuleLabel);
388 pmalgTracker.init(hitsFromClusters, hitsFromEmParts);
393 if (init<4>(evt, pmalgTracker)) { mvaLength = 4; }
394 else if (init<3>(evt, pmalgTracker)) {
397 else if (init<2>(evt, pmalgTracker)) {
401 throw cet::exception(
"PMAlgTrackMaker") <<
"No EM/track MVA data products." << std::endl;
406 auto cluListHandle = evt.getValidHandle<std::vector<recob::Cluster>>(
fCluModuleLabel);
407 art::FindManyP<recob::Hit> hitsFromClusters(cluListHandle, evt,
fCluModuleLabel);
408 pmalgTracker.init(hitsFromClusters);
412 auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
414 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clockData);
415 int retCode = pmalgTracker.build(clockData,
detProp);
418 case -2: mf::LogError(
"Summary") <<
"problem";
break;
419 case -1: mf::LogWarning(
"Summary") <<
"no input";
break;
420 case 0: mf::LogVerbatim(
"Summary") <<
"no tracks done";
break;
423 mf::LogVerbatim(
"Summary") <<
"unknown result";
424 else if (retCode == 1)
425 mf::LogVerbatim(
"Summary") << retCode <<
" track ready";
427 mf::LogVerbatim(
"Summary") << retCode <<
" tracks ready";
432 auto const& result = pmalgTracker.result();
435 size_t spStart = 0, spEnd = 0;
436 double sp_pos[3], sp_err[6];
437 for (
size_t i = 0; i < 3; ++i)
439 for (
size_t i = 0; i < 6; ++i)
442 auto const make_pfpptr = art::PtrMaker<recob::PFParticle>(
evt);
443 auto const make_trkptr = art::PtrMaker<recob::Track>(
evt);
444 auto const make_vtxptr = art::PtrMaker<recob::Vertex>(
evt);
445 auto const make_kinkptr = art::PtrMaker<recob::Vertex>(
evt,
kKinksName);
446 auto const make_t0ptr = art::PtrMaker<anab::T0>(
evt);
447 auto const make_ctptr = art::PtrMaker<anab::CosmicTag>(
evt);
449 tracks->reserve(result.size());
450 for (
size_t trkIndex = 0; trkIndex < result.size(); ++trkIndex) {
478 if (trk->
size() < 2)
continue;
482 pdg = getPdgFromCnnOnHits<4>(
evt, *(result[trkIndex].Track()));
483 else if (mvaLength == 3)
484 pdg = getPdgFromCnnOnHits<3>(
evt, *(result[trkIndex].Track()));
485 else if (mvaLength == 2)
486 pdg = getPdgFromCnnOnHits<2>(
evt, *(result[trkIndex].Track()));
491 auto const trkPtr = make_trkptr(
tracks->size() - 1);
497 auto const t0Ptr = make_t0ptr(t0s->size() - 1);
498 trk2t0->addSingle(trkPtr, t0Ptr);
504 std::vector<float> trkEnd0;
505 std::vector<float> trkEnd1;
511 for (
int i = 0; i < 3; ++i) {
515 if (i == driftDir) { shift = trk->
Nodes()[0]->GetDriftShift(); }
516 trkEnd0.push_back(trk->
Nodes()[0]->Point3D()[i] -
shift);
517 trkEnd1.push_back(trk->
Nodes()[trk->
Nodes().size() - 1]->Point3D()[i] -
shift);
522 for (
const auto t : tags) {
523 cosmicTags->emplace_back(trkEnd0, trkEnd1, 1, t);
524 auto const cosmicPtr = make_ctptr(cosmicTags->size() - 1);
525 trk2ct->addSingle(trkPtr, cosmicPtr);
530 for (
size_t h = 0, cnt = 0;
h < trk->
size();
h++) {
535 trk2hit->addSingle(trkPtr, h3d->
Hit2DPtr(), metadata);
536 trk2hit_oldway->addSingle(
540 art::PtrVector<recob::Hit> sp_hits;
541 spStart = allsp->size();
543 for (
size_t h = 0;
h < trk->
size(); ++
h) {
547 double hx = h3d->
Point3D().X();
548 double hy = h3d->
Point3D().Y();
549 double hz = h3d->
Point3D().Z();
551 if ((
h == 0) || (std::fabs(sp_pos[0] - hx) > 1.0
e-5) ||
552 (std::fabs(sp_pos[1] - hy) > 1.0
e-5) || (std::fabs(sp_pos[2] - hz) > 1.0
e-5)) {
570 spEnd = allsp->size();
575 auto vsel = pmalgTracker.getVertices(
577 auto ksel = pmalgTracker.getKinks();
578 std::map<size_t, art::Ptr<recob::Vertex>> frontVtxs;
583 for (
auto const& v : vsel) {
584 xyz[0] = v.first.X();
585 xyz[1] = v.first.Y();
586 xyz[2] = v.first.Z();
587 mf::LogVerbatim(
"Summary") <<
" vtx:" << xyz[0] <<
":" << xyz[1] <<
":" << xyz[2]
588 <<
" (" << v.second.size() <<
" tracks)";
590 size_t vidx = vtxs->size();
591 vtxs->push_back(recob::Vertex(xyz, vidx));
593 auto const vptr = make_vtxptr(vidx);
594 if (!v.second.empty()) {
595 for (
const auto& vEntry : v.second) {
596 size_t tidx = vEntry.first;
597 bool isFront = vEntry.second;
599 if (isFront) frontVtxs[tidx] = vptr;
601 auto const tptr = make_trkptr(tidx);
602 vtx2trk->addSingle(vptr, tptr);
606 mf::LogWarning(
"PMAlgTrackMaker") <<
"No tracks found at this vertex.";
608 mf::LogVerbatim(
"Summary") << vtxs->size() <<
" vertices ready";
610 for (
auto const&
k : ksel) {
611 xyz[0] =
k.first.X();
612 xyz[1] =
k.first.Y();
613 xyz[2] =
k.first.Z();
614 mf::LogVerbatim(
"Summary") <<
" kink:" << xyz[0] <<
":" << xyz[1] <<
":" << xyz[2];
616 size_t kidx = kinks->size();
617 size_t tidx =
k.second;
620 recob::Vertex(xyz, tidx));
622 auto const tptr = make_trkptr(tidx);
623 auto const kptr = make_kinkptr(kidx);
624 trk2kink->addSingle(tptr, kptr);
626 mf::LogVerbatim(
"Summary") << ksel.size() <<
" kinks ready";
631 for (
size_t t = 0; t < result.size(); ++t) {
632 auto const& trk = *(result[t].Track());
633 for (
auto const* node : trk.Nodes()) {
634 xyz[0] = node->Point3D().X();
635 xyz[1] = node->Point3D().Y();
636 xyz[2] = node->Point3D().Z();
637 nodes->push_back(recob::Vertex(xyz, t));
642 for (
size_t t = 0; t < result.size(); ++t) {
644 if (result[t].Parent() >= 0) parentIdx = (
size_t)result[t].Parent();
646 std::vector<size_t> daughterIdxs;
647 for (
size_t idx : result[t].Daughters()) {
648 daughterIdxs.push_back(idx);
651 size_t pfpidx = pfps->size();
652 pfps->emplace_back((*
tracks)[t].ParticleId(), pfpidx, parentIdx, daughterIdxs);
654 auto const pfpptr = make_pfpptr(pfpidx);
655 auto const tptr = make_trkptr(t);
656 pfp2trk->addSingle(pfpptr, tptr);
660 art::Ptr<recob::Vertex> vptr = frontVtxs[t];
662 pfp2vtx->addSingle(pfpptr, vptr);
664 mf::LogWarning(
"PMAlgTrackMaker") <<
"Front vertex for PFParticle is missing.";
667 mf::LogVerbatim(
"Summary") << pfps->size()
668 <<
" PFParticles created for reconstructed tracks.";
669 mf::LogVerbatim(
"Summary") <<
"Adding " << result.parents().size() <<
" primary PFParticles.";
670 for (
size_t t = 0; t < result.parents().size(); ++t) {
671 std::vector<size_t> daughterIdxs;
672 for (
size_t idx : result.parents()[t].Daughters()) {
673 daughterIdxs.push_back(idx);
676 size_t pfpidx = pfps->size();
678 pfps->emplace_back(0, pfpidx, parentIdx, daughterIdxs);
682 auto const pfpptr = make_pfpptr(pfpidx);
683 art::Ptr<recob::Vertex> vptr =
684 frontVtxs[daughterIdxs.front()];
686 pfp2vtx->addSingle(pfpptr, vptr);
688 mf::LogWarning(
"PMAlgTrackMaker") <<
"Front vertex for PFParticle is missing.";
691 mf::LogVerbatim(
"Summary") << pfps->size() <<
" PFParticles created in total.";
696 evt.put(std::move(
tracks));
697 evt.put(std::move(allsp));
698 evt.put(std::move(vtxs));
701 evt.put(std::move(t0s));
702 evt.put(std::move(cosmicTags));
704 evt.put(std::move(trk2hit_oldway));
705 evt.put(std::move(trk2hit));
706 evt.put(std::move(trk2sp));
707 evt.put(std::move(trk2t0));
708 evt.put(std::move(trk2ct));
710 evt.put(std::move(sp2hit));
711 evt.put(std::move(vtx2trk));
714 evt.put(std::move(pfps));
715 evt.put(std::move(pfp2clu));
716 evt.put(std::move(pfp2vtx));
717 evt.put(std::move(pfp2trk));
PMAlgTrackMaker & operator=(PMAlgTrackMaker const &)=delete
bool SelectHits(float fraction=1.0F)
bool HasPlane(unsigned int iplane) const
Returns whether a plane with index iplane is present in this TPC.
double Dx() const noexcept
bool HasTagFlag(ETag value) const noexcept
static const std::string kKinksName
ClusterModuleLabel join with tracks
void produce(art::Event &e) override
recob::Track convertFrom(const pma::Track3D &src, unsigned int tidx, int pdg=0)
fhicl::Atom< art::InputTag > EmClusterModuleLabel
static constexpr size_t kPFParticlePrimary
Define index to signify primary particle.
Declaration of signal hit object.
fhicl::Atom< art::InputTag > WireModuleLabel
fhicl::Atom< art::InputTag > HitModuleLabel
fhicl::Table< pma::PMAlgVertexing::Config > PMAlgVertexing
Planes which measure X direction.
fhicl::Table< pma::PMAlgCosmicTagger::Config > PMAlgCosmicTagging
ETag GetTag() const noexcept
fhicl::Atom< bool > SavePmaNodes
fhicl::Table< pma::ProjectionMatchingAlg::Config > ProjectionMatchingAlg
fhicl::Atom< art::InputTag > ClusterModuleLabel
std::vector< pma::Node3D * > const & Nodes() const noexcept
TVector3 const & Point3D() const
Planes which measure Z direction.
fhicl::Atom< bool > RunVertexing
Definition of vertex object for LArSoft.
Planes which measure Y direction.
std::vector< anab::CosmicTagID_t > getCosmicTag(const pma::Track3D::ETag pmaTag) const
process_name ccluster WireModuleLabel
geo::GeometryCore const * fGeom
pma::PMAlgStitching::Config fPmaStitchConfig
pma::ProjectionMatchingAlg::Config fPmaConfig
pma::PMAlgVertexing::Config fPmaVtxConfig
int getPdgFromCnnOnHits(const art::Event &evt, const pma::Track3D &trk) const
art::InputTag fCluModuleLabel
BEGIN_PROLOG vertical distance to the surface Name
unsigned int FrontTPC() const
unsigned int FrontCryo() const
pma::PMAlgCosmicTagger::Config fPmaTaggingConfig
Description of geometry of one entire detector.
Declaration of cluster object.
Provides recob::Track data product.
art::InputTag fHitModuleLabel
size_t CompleteMissingWires(detinfo::DetectorPropertiesData const &detProp, unsigned int view)
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, std::vector< double > > dedx_map
fhicl::Atom< float > TrackLikeThreshold
double GetRawdEdxSequence(std::map< size_t, std::vector< double >> &dedx, unsigned int view=geo::kZ, unsigned int skip=0, bool inclDisabled=false) const
void init(const art::FindManyP< recob::Hit > &hitsFromClusters)
bool HasT0() const noexcept
fhicl::Table< pma::PMAlgTracker::Config > PMAlgTracking
bool init(const art::Event &evt, pma::PMAlgTracker &pmalgTracker) const
art::InputTag fEmModuleLabel
fhicl::Table< pma::PMAlgStitching::Config > PMAlgStitching
art::InputTag fWireModuleLabel
art::Ptr< recob::Hit > const & Hit2DPtr() const
art::EDProducer::Table< Config > Parameters
std::vector< TH1F * > fAdcInRejectedPoints
bool fSaveOnlyBranchingVtx
bool IsEnabled() const noexcept
TrackCollectionProxyElement< TrackCollProxy > Track
Proxy to an element of a proxy collection of recob::Track objects.
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
pma::PMAlgTracker::Config fPmaTrackerConfig
2D representation of charge deposited in the TDC/wire plane
art::ServiceHandle< art::TFileService > tfs
PMAlgTrackMaker(Parameters const &config)
static std::unique_ptr< MVAReader > create(const art::Event &evt, const art::InputTag &tag)
art framework interface to geometry description
std::vector< TH1F * > fAdcInPassingPoints
Encapsulate the construction of a single detector plane.
fhicl::Atom< bool > SaveOnlyBranchingVtx
static const std::string kNodesName