13 #include "canvas/Utilities/InputTag.h"
14 #include "canvas/Persistency/Provenance/EventID.h"
15 #include "art/Framework/Principal/Provenance.h"
16 #include "art/Framework/Core/EDAnalyzer.h"
17 #include "art/Framework/Principal/Event.h"
20 #include "fhiclcpp/types/Atom.h"
21 #include "fhiclcpp/types/OptionalAtom.h"
139 Name(
"PFModuleLabel"),
140 Comment(
"label of producer of the recob::PFParticle to be dumped")
144 Name(
"OutputCategory"),
145 Comment(
"message facility category used for output (for filtering)"),
150 Name(
"PrintHexFloats"),
151 Comment(
"print all the floating point numbers in base 16"),
157 Comment(
"at most this number of particle generations will be printed")
161 Name(
"MakeParticleGraphs"),
162 Comment(
"creates a DOT file with particle information for each event"),
174 virtual void analyze (
const art::Event&
evt)
override;
186 (art::EventID
const& evtID, art::Provenance
const& prodInfo);
189 art::Event
const& event,
190 art::ValidHandle<std::vector<recob::PFParticle>>
const& handle
211 #include "art/Framework/Core/ModuleMacros.h"
212 #include "canvas/Persistency/Common/FindOne.h"
213 #include "canvas/Persistency/Common/FindMany.h"
214 #include "art/Framework/Principal/Handle.h"
217 #include "messagefacility/MessageLogger/MessageLogger.h"
231 template <
typename T>
233 using map_type = std::vector<T>;
235 using this_type = int_map<T>;
237 using typename map_type::value_type;
238 using typename map_type::reference;
239 using typename map_type::const_reference;
240 using typename map_type::iterator;
241 using typename map_type::const_iterator;
243 using typename map_type::size_type;
250 int_map(value_type invalid_value): invalid(invalid_value) {}
254 void resize(
size_t new_size)
255 { get_map().resize(new_size, invalid_value()); }
258 reference operator[] (
size_t pos)
259 {
if (pos >=
size()) resize(pos + 1);
return get_map()[pos]; }
262 const_reference operator[] (
size_t pos)
const
263 {
return (pos >=
size())? invalid: get_map()[pos]; }
272 using map_type::rbegin;
273 using map_type::rend;
274 using map_type::crbegin;
275 using map_type::crend;
278 void swap(this_type& data)
279 { swap(data.get_map()); std::swap(data.invalid, invalid); }
282 void swap(std::vector<T>& data) { map_type::swap(data); }
286 size_type n_invalid()
const
290 size_type n_valid()
const {
return size() - n_invalid(); }
293 bool is_valid(size_type pos)
const
294 {
return (pos <
size())? is_valid_value(get_map()[pos]):
false; }
297 bool is_valid_value(value_type
const& v)
const {
return v != invalid; }
300 value_type
const& invalid_value()
const {
return invalid; }
304 value_type
const invalid;
306 map_type& get_map() {
return static_cast<map_type&
>(*this); }
307 map_type
const& get_map()
const
308 {
return static_cast<map_type
const&
>(*this); }
314 int_map<size_t> CreateMap(std::vector<recob::PFParticle>
const& particles) {
316 int_map<size_t> pmap(std::numeric_limits<size_t>::max());
317 pmap.resize(particles.size());
319 size_t const nParticles = particles.size();
320 for (
size_t iPart = 0; iPart < nParticles; ++iPart)
321 pmap[particles[iPart].Self()] = iPart;
329 auto const& daughters = particle.
Daughters();
330 return daughters.end()
331 != std::find(daughters.begin(), daughters.end(), partID);
336 class ParticleDumper {
340 struct PrintOptions_t {
341 bool hexFloats =
false;
343 unsigned int maxDepth = std::numeric_limits<unsigned int>::max();
345 std::string streamName;
350 ParticleDumper(std::vector<recob::PFParticle>
const& particle_list)
351 : ParticleDumper(particle_list, {})
356 std::vector<recob::PFParticle>
const& particle_list,
357 PrintOptions_t print_options
359 : particles(particle_list)
361 , visited(particles.
size(), 0U)
362 , particle_map (CreateMap(particles))
367 void SetVertices(art::FindOne<recob::Vertex>
const* vtx_query)
368 { vertices = vtx_query; }
371 void SetTracks(art::FindMany<recob::Track>
const* trk_query)
375 void SetClusters(art::FindMany<recob::Cluster>
const* cls_query)
376 { clusters = cls_query; }
379 void SetSeeds(art::FindMany<recob::Seed>
const* seed_query)
380 {
seeds = seed_query; }
383 void SetSpacePoints(art::FindMany<recob::SpacePoint>
const* sp_query)
384 { spacepoints = sp_query; }
387 void SetPCAxes(art::FindMany<recob::PCAxis>
const* pca_query)
388 { pcaxes = pca_query; }
393 template <
typename Stream>
395 Stream&& out,
size_t iPart, std::string indentstr =
"",
402 template <
typename Stream>
403 void DumpParticleWithID(
404 Stream&& out,
size_t pID, std::string indentstr =
"",
410 void DumpAllPrimaries(std::string indentstr =
"")
const;
414 void DumpAllParticles(std::string indentstr =
"")
const;
417 template <
typename Stream>
418 static void DumpPDGID(
Stream&& out,
int ID);
422 std::vector<recob::PFParticle>
const& particles;
427 art::FindOne<recob::Vertex>
const* vertices =
nullptr;
430 art::FindMany<recob::Track>
const*
tracks =
nullptr;
433 art::FindMany<recob::Cluster>
const* clusters =
nullptr;
436 art::FindMany<recob::Seed>
const*
seeds =
nullptr;
439 art::FindMany<recob::SpacePoint>
const* spacepoints =
nullptr;
442 art::FindMany<recob::PCAxis>
const* pcaxes =
nullptr;
445 mutable std::vector<unsigned int> visited;
447 int_map<size_t>
const particle_map;
450 template <
typename Stream>
451 void DumpPFParticleInfo(
455 std::string indentstr
458 template <
typename Stream>
461 cet::maybe_ref<recob::Vertex const> VertexRef,
462 std::string indentstr
465 template <
typename Stream>
466 void DumpPCAxisDirection
469 template <
typename Stream>
472 std::vector<recob::PCAxis const*>
const& myAxes,
473 std::string indentstr
476 template <
typename Stream>
479 template <
typename Stream>
482 std::vector<recob::Track const*>
const& myTracks,
483 std::string indentstr
486 template <
typename Stream>
490 template <
typename Stream>
493 std::vector<recob::Seed const*>
const& mySeeds,
494 std::string indentstr
497 template <
typename Stream>
500 template <
typename Stream>
501 void DumpSpacePoints(
503 std::vector<recob::SpacePoint const*>
const& mySpacePoints,
504 std::string indentstr
507 template <
typename Stream>
510 template <
typename Stream>
513 std::vector<recob::Cluster const*>
const& myClusters,
514 std::string indentstr
521 class PFParticleGraphMaker {
524 PFParticleGraphMaker() =
default;
526 template <
typename Stream>
528 (
Stream&& out, std::vector<recob::PFParticle>
const& particles)
const;
530 template <
typename Stream>
531 void WriteGraphHeader(
Stream&& out)
const;
533 template <
typename Stream>
534 void WriteParticleRelations
535 (
Stream&& out, std::vector<recob::PFParticle>
const& particles)
const;
537 template <
typename Stream>
538 void WriteParticleNodes
539 (
Stream&& out, std::vector<recob::PFParticle>
const& particles)
const;
541 template <
typename Stream>
542 void WriteParticleEdges
543 (
Stream&& out, std::vector<recob::PFParticle>
const& particles)
const;
545 template <
typename Stream>
546 void WriteGraphFooter(
Stream&& out)
const;
554 template <
typename Stream>
555 void ParticleDumper::DumpParticle(
556 Stream&& out,
size_t iPart, std::string indentstr ,
565 if (visited[iPart] > 1) {
566 out << indentstr <<
"particle " << part.
Self()
567 <<
" already printed!!!";
574 DumpPFParticleInfo(std::forward<Stream>(out), part, iPart, indentstr);
580 DumpVertex(std::forward<Stream>(out), vertices->at(iPart), indentstr);
586 out <<
" with no daughter";
592 DumpPCAxes(std::forward<Stream>(out), pcaxes->at(iPart), indentstr);
598 DumpTracks(std::forward<Stream>(out),
tracks->at(iPart), indentstr);
604 DumpSeeds(std::forward<Stream>(out),
seeds->at(iPart), indentstr);
611 (std::forward<Stream>(out), spacepoints->at(iPart), indentstr);
619 (std::forward<Stream>(out), clusters->at(iPart), indentstr);
625 auto const PartID = part.
Self();
627 std::vector<size_t>
const& daughters = part.
Daughters();
628 out <<
"\n" << indentstr
632 for (
size_t DaughterID: daughters) {
633 if (DaughterID == PartID) {
634 out <<
"\n" << indentstr
635 <<
" oh, just great: this particle is its own daughter!";
639 DumpParticleWithID(out, DaughterID, indentstr +
" ", gen - 1);
644 out <<
" (further descend suppressed)";
651 if (visited[iPart] == 2) {
652 out <<
"\n" << indentstr <<
" WARNING: particle ID=" << PartID
653 <<
" connected more than once!";
664 template <
typename Stream>
665 void ParticleDumper::DumpParticleWithID(
666 Stream&& out,
size_t pID, std::string indentstr ,
669 size_t const pos = particle_map[pID];
670 if (particle_map.is_valid_value(pos)) {
671 DumpParticle(out, pos, indentstr, gen);
674 out << indentstr <<
"<ID=" << pID <<
" not found>";
680 void ParticleDumper::DumpAllPrimaries(std::string indentstr )
const
683 size_t const nParticles = particles.size();
684 unsigned int nPrimaries = 0;
685 for (
size_t iPart = 0; iPart < nParticles; ++iPart) {
686 if (!particles[iPart].
IsPrimary())
continue;
688 mf::LogVerbatim(
options.streamName),
689 iPart, indentstr,
options.maxDepth
692 if (nPrimaries == 0) {
693 mf::LogVerbatim(
options.streamName)
694 << indentstr <<
"No primary particle found";
700 void ParticleDumper::DumpAllParticles(std::string indentstr )
const
703 DumpAllPrimaries(indentstr);
705 unsigned int const nDisconnected
706 =
std::count(visited.begin(), visited.end(), 0U);
708 mf::LogVerbatim(
options.streamName) << indentstr
709 << nDisconnected <<
" particles not coming from primary ones:";
710 size_t const nParticles = visited.size();
711 for (
size_t iPart = 0; iPart < nParticles; ++iPart) {
712 if (visited[iPart] > 0)
continue;
714 mf::LogVerbatim(
options.streamName), iPart, indentstr +
" ",
718 mf::LogVerbatim(
options.streamName) << indentstr
719 <<
"(end of " << nDisconnected <<
" particles not from primaries)";
727 template <
typename Stream>
728 void ParticleDumper::DumpPDGID(
Stream&& out,
int ID) {
730 case -11: out <<
"e+";
break;
731 case 11: out <<
"e-";
break;
732 case -13: out <<
"mu+";
break;
733 case 13: out <<
"mu-";
break;
734 default: out <<
"MCID=" << ID;
break;
740 template <
typename Stream>
741 void ParticleDumper::DumpPFParticleInfo(
745 std::string indentstr
748 auto const PartID = part.
Self();
749 out << indentstr <<
"ID=" << PartID;
750 if (iPart != PartID) out <<
" [#" << iPart <<
"]";
752 DumpPDGID(out, part.
PdgCode());
754 if (part.
IsPrimary()) out <<
" (primary)";
755 else out <<
" from ID=" << part.
Parent();
759 template <
typename Stream>
760 void ParticleDumper::DumpVertex(
762 cet::maybe_ref<recob::Vertex const> VertexRef,
763 std::string indentstr
766 if (!VertexRef.isValid()) {
767 out <<
" [no vertex found!]";
771 std::array<double, 3> vtx_pos;
772 vertex.
XYZ(vtx_pos.data());
774 out <<
" [decay at ("
775 << hexfloat(vtx_pos[0]) <<
"," << hexfloat(vtx_pos[1])
776 <<
"," << hexfloat(vtx_pos[2])
777 <<
"), ID=" << vertex.
ID() <<
"]";
782 template <
typename Stream>
783 void ParticleDumper::DumpPCAxisDirection
787 out <<
"axis is invalid";
791 out <<
"axis ID=" << axis.
getID() <<
", principal: ("
797 template <
typename Stream>
798 void ParticleDumper::DumpPCAxes(
800 std::vector<recob::PCAxis const*>
const& myAxes,
801 std::string indentstr
804 out <<
"\n" << indentstr;
805 if (myAxes.empty()) {
806 out <<
" [no axis found!]";
809 if (myAxes.size() == 1) {
810 DumpPCAxisDirection(std::forward<Stream>(out), *(myAxes.front()));
813 out <<
" " << myAxes.size() <<
" axes present:";
815 out <<
"\n" << indentstr <<
" ";
816 DumpPCAxisDirection(std::forward<Stream>(out), *axis);
822 template <
typename Stream>
823 void ParticleDumper::DumpSeed
830 std::array<double, 3> start,
dir;
832 seed.
GetPoint(start.data(),
nullptr);
834 out <<
"\n" << indentstr
835 <<
" (" << hexfloat(start[0]) <<
"," << hexfloat(start[1])
836 <<
"," << hexfloat(start[2])
837 <<
")=>(" << hexfloat(dir[0]) <<
"," << hexfloat(dir[1])
838 <<
"," << hexfloat(dir[2])
839 <<
"), " << hexfloat(seed.
GetLength()) <<
" cm"
843 template <
typename Stream>
844 void ParticleDumper::DumpSeeds(
846 std::vector<recob::Seed const*>
const& mySeeds,
847 std::string indentstr
850 if (mySeeds.empty())
return;
851 out <<
"\n" << indentstr <<
" "
852 << mySeeds.size() <<
" seeds:";
854 DumpSeed(std::forward<Stream>(out), *seed, indentstr);
858 template <
typename Stream>
862 const double* pos = sp.
XYZ();
864 out <<
" ID=" << sp.
ID()
865 <<
" at (" << hexfloat(pos[0]) <<
"," << hexfloat(pos[1])
866 <<
"," << hexfloat(pos[2]) <<
") cm"
870 template <
typename Stream>
871 void ParticleDumper::DumpSpacePoints(
873 std::vector<recob::SpacePoint const*>
const& mySpacePoints,
874 std::string indentstr
877 out <<
"\n" << indentstr <<
" ";
878 if (mySpacePoints.empty()) {
879 out <<
"no space points";
882 constexpr
unsigned int PointsPerLine = 2;
883 out << mySpacePoints.size() <<
" space points:";
884 for (
size_t iSP = 0; iSP < mySpacePoints.size(); ++iSP) {
885 if ((iSP % PointsPerLine) == 0)
886 out <<
"\n" << indentstr <<
" ";
893 template <
typename Stream>
897 out <<
" length " << hexfloat(track.
Length())
898 <<
"cm from (" << hexfloat(track.
Vertex().X())
899 <<
";" << hexfloat(track.
Vertex().Y())
900 <<
";" << hexfloat(track.
Vertex().Z())
901 <<
") to (" << hexfloat(track.
End().X())
902 <<
";" << hexfloat(track.
End().Y())
903 <<
";" << hexfloat(track.
End().Z())
904 <<
") (ID=" << track.
ID() <<
")";
907 template <
typename Stream>
908 void ParticleDumper::DumpTracks(
910 std::vector<recob::Track const*>
const& myTracks,
911 std::string indentstr
914 if (myTracks.empty())
return;
915 out <<
"\n" << indentstr <<
" "
916 << myTracks.size() <<
" tracks:";
918 if (myTracks.size() > 1) out <<
"\n" << indentstr <<
" ";
919 DumpTrack(std::forward<Stream>(out), *track);
924 template <
typename Stream>
925 void ParticleDumper::DumpClusterSummary
928 out <<
" " << cluster.
NHits() <<
" hits on " << cluster.
Plane()
929 <<
" (ID=" << cluster.
ID() <<
")";
932 template <
typename Stream>
933 void ParticleDumper::DumpClusters(
935 std::vector<recob::Cluster const*>
const& myClusters,
936 std::string indentstr
939 if (myClusters.empty())
return;
940 out <<
"\n" << indentstr <<
" "
941 << myClusters.size() <<
" clusters:";
943 if (myClusters.size() > 1) out <<
"\n" << indentstr <<
" ";
944 DumpClusterSummary(std::forward<Stream>(out), *cluster);
952 template <
typename Stream>
953 void PFParticleGraphMaker::MakeGraph
954 (
Stream&& out, std::vector<recob::PFParticle>
const& particles)
const
957 WriteGraphHeader (std::forward<Stream>(out));
958 WriteParticleRelations(std::forward<Stream>(out), particles);
959 WriteGraphFooter (std::forward<Stream>(out));
965 template <
typename Stream>
966 void PFParticleGraphMaker::WriteGraphHeader(
Stream&& out)
const {
973 template <
typename Stream>
974 void PFParticleGraphMaker::WriteParticleNodes
975 (
Stream&& out, std::vector<recob::PFParticle>
const& particles)
const
978 for (
auto const& particle: particles) {
980 std::ostringstream label;
981 label <<
"#" << particle.
Self();
984 ParticleDumper::DumpPDGID(label, particle.
PdgCode());
987 out <<
"\n P" << particle.
Self()
989 <<
" label = \"" << label.str() <<
"\"";
990 if (particle.
IsPrimary()) out <<
", style = bold";
997 template <
typename Stream>
998 void PFParticleGraphMaker::WriteParticleEdges
999 (
Stream&& out, std::vector<recob::PFParticle>
const& particles)
const
1001 auto particle_map = CreateMap(particles);
1005 <<
"\n // relations"
1007 <<
"\n // the arrow is close to the information provider,;"
1008 <<
"\n // and it points from parent to daughter"
1014 for (
auto const& particle: particles) {
1015 auto const partID = particle.
Self();
1019 auto const parentID = particle.
Parent();
1020 size_t const iParent = particle_map[parentID];
1021 if (!particle_map.is_valid_value(iParent)) {
1024 <<
"\nP" << parentID
1025 <<
" [ style = dashed, color = red"
1026 <<
", label = \"(#" << parentID <<
")\" ] // ghost particle"
1027 <<
"\nP" << parentID <<
" -> P" << partID
1028 <<
" [ dir = both, arrowhead = empty, arrowtail = none ]";
1035 if (hasDaughter(parent, partID)) {
1037 <<
"\nP" << parentID <<
" -> P" << partID
1038 <<
" [ dir = both, arrowtail = inv ]";
1042 <<
"\nP" << parentID <<
" -> P" << partID
1043 <<
" [ dir = forward, color = red ]"
1044 <<
" // claimed parent";
1051 for (
auto daughterID: particle.
Daughters()) {
1052 size_t const iDaughter = particle_map[daughterID];
1053 if (!particle_map.is_valid_value(iDaughter)) {
1056 <<
"\nP" << daughterID
1057 <<
" [ style = dashed, color = red"
1058 <<
", label = \"(#" << daughterID <<
")\" ] // ghost daughter"
1059 <<
"\nP" << partID <<
" -> P" << daughterID
1060 <<
" [ dir = both, arrowhead = none, arrowtail = invempty ]";
1067 if (daughter.
Parent() != partID) {
1069 <<
"\nP" << partID <<
" -> P" << daughterID
1070 <<
" [ dir = both, arrowhead = none, arrowtail = inv, color = orange ]"
1071 <<
" // claimed daughter";
1084 template <
typename Stream>
1085 void PFParticleGraphMaker::WriteParticleRelations
1086 (
Stream&& out, std::vector<recob::PFParticle>
const& particles)
const
1088 out <<
"\n // " << particles.size() <<
" particles (nodes)";
1089 WriteParticleNodes(std::forward<Stream>(out), particles);
1093 <<
"\n // parent/children relations";
1094 WriteParticleEdges(std::forward<Stream>(out), particles);
1099 template <
typename Stream>
1100 void PFParticleGraphMaker::WriteGraphFooter(
Stream&& out)
const {
1119 : EDAnalyzer(config)
1120 , fInputTag(config().PFModuleLabel())
1121 , fOutputCategory(config().OutputCategory())
1122 , fPrintHexFloats(config().PrintHexFloats())
1123 , fMaxDepth(
std::numeric_limits<unsigned int>::max())
1124 , fMakeEventGraphs(config().MakeParticleGraphs())
1129 fMaxDepth = std::numeric_limits<unsigned int>::max();
1135 (art::EventID
const& evtID, art::Provenance
const& prodInfo)
1137 return prodInfo.processName()
1138 +
'_' + prodInfo.moduleLabel()
1139 +
'_' + prodInfo.productInstanceName()
1149 art::Event
const& event,
1150 art::ValidHandle<std::vector<recob::PFParticle>>
const& handle
1152 art::EventID
const eventID =
event.id();
1154 std::ofstream
outFile(fileName);
1157 <<
"// " << fileName
1159 <<
"\n// Created for run " << eventID.run()
1160 <<
" subrun " << eventID.subRun()
1161 <<
" event " << eventID.event()
1163 <<
"\n// dump of " << handle->size() <<
" particles"
1167 PFParticleGraphMaker graphMaker;
1168 graphMaker.MakeGraph(outFile, *handle);
1180 art::ValidHandle<std::vector<recob::PFParticle>> PFParticles
1181 = evt.getValidHandle<std::vector<recob::PFParticle>>(
fInputTag);
1186 art::FindOne<recob::Vertex>
const ParticleVertices
1188 art::FindMany<recob::Track>
const ParticleTracks
1190 art::FindMany<recob::Cluster>
const ParticleClusters
1192 art::FindMany<recob::Seed>
const ParticleSeeds
1194 art::FindMany<recob::SpacePoint>
const ParticleSpacePoints
1196 art::FindMany<recob::PCAxis>
const ParticlePCAxes
1199 size_t const nParticles = PFParticles->size();
1201 <<
" contains " << nParticles <<
" particles from '"
1205 ParticleDumper::PrintOptions_t
options;
1209 ParticleDumper dumper(*PFParticles, options);
1210 if (ParticleVertices.isValid()) dumper.SetVertices(&ParticleVertices);
1211 else mf::LogPrint(
"DumpPFParticles") <<
"WARNING: vertex information not available";
1212 if (ParticleTracks.isValid()) dumper.SetTracks(&ParticleTracks);
1213 else mf::LogPrint(
"DumpPFParticles") <<
"WARNING: track information not available";
1214 if (ParticleClusters.isValid()) dumper.SetClusters(&ParticleClusters);
1215 else mf::LogPrint(
"DumpPFParticles") <<
"WARNING: cluster information not available";
1216 if (ParticleSeeds.isValid()) dumper.SetSeeds(&ParticleSeeds);
1217 else mf::LogPrint(
"DumpPFParticles") <<
"WARNING: seed information not avaialble";
1218 if (ParticleSpacePoints.isValid())
1219 dumper.SetSpacePoints(&ParticleSpacePoints);
1221 mf::LogPrint(
"DumpPFParticles")
1222 <<
"WARNING: space point information not available";
1224 if (ParticlePCAxes.isValid())
1225 dumper.SetPCAxes(&ParticlePCAxes);
1227 mf::LogPrint(
"DumpPFParticles")
1228 <<
"WARNING: principal component axis not available";
1230 dumper.DumpAllParticles(
" ");
void XYZ(double *xyz) const
Legacy method to access vertex position, preserved to avoid breaking code. Please try to use Vertex::...
DumpPFParticles(Parameters const &config)
Default constructor.
const std::vector< size_t > & Daughters() const
Returns the collection of daughter particles.
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
const EigenVectors & getEigenVectors() const
art::EDAnalyzer::Table< Config > Parameters
fhicl::Atom< bool > PrintHexFloats
int NumDaughters() const
Returns the number of daughter particles flowing from this one.
ClusterModuleLabel join with tracks
size_t Self() const
Returns the index of this particle.
void GetPoint(double *Pt, double *Err) const
std::size_t size(FixedBins< T, C > const &) noexcept
fhicl::Atom< bool > MakeParticleGraphs
int PdgCode() const
Return the type of particle as a PDG ID.
auto cbegin(FixedBins< T, C > const &) noexcept
Set of hits with a 2D structure.
process_name use argoneut_mc_hitfinder track
auto DumpSpacePoint(Stream &&out, recob::SpacePoint const &sp, SpacePointPrintOptions_t const &options={}) -> std::enable_if_t< std::is_same< NewLine< std::decay_t< Stream >>, std::decay_t< NewLineRef >>::value >
Dumps the content of the specified space point into a stream.
geo::PlaneID Plane() const
Returns the plane ID this cluster lies on.
bool IsPrimary(const caf::SRTrueParticleProxy &p)
Whether this is a primary particle or generated by a secondary interaction.
fhicl::OptionalAtom< unsigned int > MaxDepth
Definition of vertex object for LArSoft.
auto cend(FixedBins< T, C > const &) noexcept
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
double Length(size_t p=0) const
Access to various track properties.
std::string fOutputCategory
category for LogInfo output
unsigned int fMaxDepth
maximum generation to print (0: only primaries)
Point_t const & Vertex() const
auto end(FixedBins< T, C > const &) noexcept
BEGIN_PROLOG vertical distance to the surface Name
bool IsPrimary() const
Returns whether the particle is the root of the flow.
const Double32_t * XYZ() const
virtual void analyze(const art::Event &evt) override
Does the printing.
Declaration of cluster object.
Helper for formatting floats in base 16.
Provides recob::Track data product.
auto begin(FixedBins< T, C > const &) noexcept
std::vector< TrajPoint > seeds
Hierarchical representation of particle flow.
Helper to support output of real numbers in base 16.
ID_t ID() const
Identifier of this cluster.
std::string to_string(WindowPattern const &pattern)
bool fMakeEventGraphs
whether to create one DOT file per event
services TFileService fileName
Prints the content of all the ParticleFlow particles on screen.
int ID() const
Return vertex id.
fhicl::Atom< std::string > OutputCategory
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker options
static std::string DotFileName(art::EventID const &evtID, art::Provenance const &prodInfo)
Point_t const & End() const
void MakePFParticleGraph(art::Event const &event, art::ValidHandle< std::vector< recob::PFParticle >> const &handle) const
art::InputTag fInputTag
input tag of the PFParticle product
unsigned int NHits() const
Number of hits in the cluster.
std::size_t count(Cont const &cont)
fhicl::Atom< art::InputTag > PFModuleLabel
bool empty(FixedBins< T, C > const &) noexcept
void GetDirection(double *Dir, double *Err) const
bool fPrintHexFloats
whether to print floats in base 16
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track: