DumpTracks_module.cc
Go to the documentation of this file.
1 /**
2  * @file DumpTracks_module.cc
3  * @brief Dumps on screen the content of the tracks
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date September 12th, 2014
6  */
7 
8 // LArSoft includes
13 
14 // support libraries
15 #include "fhiclcpp/types/Atom.h"
16 #include "fhiclcpp/types/Table.h"
17 #include "fhiclcpp/types/Name.h"
18 #include "fhiclcpp/types/Comment.h"
20 
21 // art libraries
26 #include "canvas/Persistency/Common/FindManyP.h"
28 
29 // C//C++ standard libraries
30 #include <string>
31 #include <sstream>
32 #include <iomanip> // std::setw()
33 #include <algorithm> // std::max(), std::sort(), std::transform()
34 #include <iterator> // std::back_inserter()
35 #include <functional> // std::mem_fn()
36 #include <memory> // std::unique_ptr()
37 
38 
39 namespace {
40 
41  /// Returns the length of the string representation of the specified object
42  template <typename T>
43  size_t StringLength(const T& value) {
44  std::ostringstream sstr;
45  sstr << value;
46  return sstr.str().length();
47  } // StringLength()
48 
49  /**
50  * @brief Prints a table with compact integers
51  * @param log stream to send the output to
52  * @param Indices sorted container of the indices to be printed
53  * @param IndicesPerLine number of indices printed in one line
54  * @param IndentStr string to be printed at the beginning of each new line
55  *
56  */
57  template <typename STREAM, typename CONT>
58  void PrintCompactIndexTable(
59  STREAM& log, const CONT& Indices, unsigned int IndicesPerLine,
60  std::string IndentStr = "")
61  {
62  unsigned int Padding = StringLength(Indices.back());
63 
64  typename CONT::const_iterator iIndex = Indices.begin(),
65  iend = Indices.end();
66  size_t RangeStart = *iIndex, RangeStop = RangeStart;
67  std::ostringstream output_line;
68  size_t nItemsInLine = 0;
69  while (++iIndex != iend) {
70 
71  if (*iIndex == RangeStop + 1) {
72  ++RangeStop;
73  }
74  else {
75  // the new item does not belong to the current range:
76  // - print the current range
77  if (nItemsInLine) output_line << " ";
78  if (RangeStart == RangeStop) {
79  output_line << std::setw(Padding) << RangeStart;
80  ++nItemsInLine;
81  }
82  else {
83  char fill = (RangeStart + 1 == RangeStop)? ' ': '-';
84  output_line << std::setw(Padding) << RangeStart
85  << fill << fill
86  << std::setw(Padding) << std::setfill(fill) << RangeStop
87  << std::setfill(' ');
88  nItemsInLine += 2;
89  }
90  // - start a new one
91  RangeStart = RangeStop = *iIndex;
92  } // if ... else
93 
94  // if we have enough stuff in the buffer, let's print it
95  if (nItemsInLine >= IndicesPerLine) {
96  nItemsInLine = 0;
97  log << IndentStr << output_line.str() << "\n";
98  output_line.str("");
99  }
100 
101  } // while
102 
103  // print what we have accumulated so far of the last line
104  log << IndentStr << output_line.str();
105  // print the last range (or single element)
106  if (nItemsInLine) log << " ";
107  if (RangeStart == RangeStop)
108  log << std::setw(Padding) << RangeStart;
109  else {
110  char fill = (RangeStart + 1 == RangeStop)? ' ': '-';
111  log << std::setw(Padding) << RangeStart
112  << fill << fill
113  << std::setw(Padding) << std::setfill(fill) << RangeStop
114  << std::setfill(' ');
115  }
116  log << std::endl;
117  } // PrintCompactIndexTable()
118 
119 
120 
121  /**
122  * @brief Prints a table with keys from a container of objects
123  * @param log stream to send the output to
124  * @param Indices sorted container of the indices to be printed
125  * @param IndicesPerLine number of indices printed in one line
126  * @param IndexExtractor functor extracting the index from a element
127  * @param IndentStr string to be printed at the beginning of each new line
128  *
129  * The key extractor must oterate on elements of Indices and returning
130  * something that can be converted to a size_t.
131  */
132  template <typename STREAM, typename CONT, typename GETINDEX>
133  void PrintCompactIndexTable(
134  STREAM& log, const CONT& Objects, unsigned int IndicesPerLine,
135  GETINDEX IndexExtractor, std::string IndentStr)
136  {
137  if ((IndicesPerLine == 0) || Objects.empty()) return;
138 
139  std::vector<size_t> Indices;
140  Indices.reserve(Objects.size());
141  std::transform(Objects.begin(), Objects.end(), std::back_inserter(Indices),
142  IndexExtractor);
143  std::sort(Indices.begin(), Indices.end());
144  PrintCompactIndexTable(log, Indices, IndicesPerLine, IndentStr);
145 
146  } // PrintCompactIndexTable()
147 
148  /**
149  * @brief Prints a table with indices from a container of objects
150  * @param log stream to send the output to
151  * @param Objects container of art::Ptr to objects to be printed
152  * @param IndicesPerLine number of indices printed in one line
153  * @param IndentStr string to be printed at the beginning of each new line
154  *
155  * The class in the container must have a key() member returning something
156  * that can be converted to a size_t.
157  * This is designed for containers like std::vector<art::Ptr<T>>.
158  */
159  template <typename STREAM, typename T>
160  inline void PrintAssociatedIndexTable(
161  STREAM& log, const std::vector<art::Ptr<T>>& Objects,
162  unsigned int IndicesPerLine, std::string IndentStr = ""
163  ) {
164  PrintCompactIndexTable(
165  log, Objects, IndicesPerLine, std::mem_fn(&art::Ptr<T>::key),
166  IndentStr
167  );
168  } // PrintAssociatedIndexTable()
169 
170 
171  /**
172  * @brief Prints a table with indices from a container of objects
173  * @param log stream to send the output to
174  * @param Objects container of art::Ptr to objects to be printed
175  * @param IndicesPerLine number of indices printed in one line
176  * @param IndentStr string to be printed at the beginning of each new line
177  *
178  * The class in the container must have a key() member returning something
179  * that can be converted to a size_t.
180  * This is designed for containers like std::vector<art::Ptr<T>>.
181  */
182  template <typename STREAM, typename T>
183  inline void PrintAssociatedIDTable(
184  STREAM& log, const std::vector<art::Ptr<T>>& Objects,
185  unsigned int IndicesPerLine, std::string IndentStr = ""
186  ) {
187  PrintCompactIndexTable(
188  log, Objects, IndicesPerLine,
189  [](const art::Ptr<T>& ptr) { return ptr->ID(); },
190  IndentStr
191  );
192  } // PrintAssociatedIDTable()
193 
194 } // local namespace
195 
196 
197 namespace recob {
198 
199  /**
200  * @brief Prints the content of all the tracks on screen
201  *
202  * This analyser prints the content of all the tracks into the
203  * LogInfo/LogVerbatim stream.
204  * The associated objects are printed only if they were produced with the
205  * same input tag as the tracks.
206  *
207  * Configuration parameters
208  * -------------------------
209  *
210  * - *TrackModuleLabel* (string, _required_): label of the
211  * producer used to create the recob::Track collection to be dumped
212  * - *OutputCategory* (string, default: `"DumpTracks"`): the category
213  * used for the output (useful for filtering)
214  * - *WayPoints* (unsigned integer, default: `10`): approximate number
215  * of way points printed in the output
216  * - *SpacePointAssociations* (boolean, default: `true`): prints the number
217  * of space points associated with the tracks
218  * - *PrintSpacePoints* (boolean, default: `false`): print the index of all hits
219  * associated with the tracks
220  * - *HitAssociations* (boolean, default: `true`): prints the number of
221  * hits associated with the tracks
222  * - *PrintHits* (boolean, default: `false`): print the index of all hits
223  * associated with the tracks
224  * - *ParticleAssociations* (boolean, default: `true`): prints the number
225  * of particle-flow particles associated with the tracks
226  *
227  */
228  class DumpTracks : public art::EDAnalyzer {
229  public:
230 
231  /// Configuration object
232  struct Config {
234  using Name = fhicl::Name;
235 
237  Name("TrackModuleLabel"),
238  Comment("input tag for the tracks to be dumped")
239  };
241  Name("OutputCategory"),
242  Comment("name of the category used for message facility output"),
243  "DumpTracks"
244  };
246  Name("WayPoints"),
247  Comment("number of points along the trajectory printed"),
248  10U
249  };
251  Name("SpacePointAssociations"),
252  Comment("prints the number of space points associated to the track"),
253  true
254  };
256  Name("PrintSpacePoints"),
257  Comment("prints the index of all space points associated to the track"),
258  false
259  };
261  Name("HitAssociations"),
262  Comment("prints the number of hits associated to the track"),
263  true
264  };
266  Name("PrintHits"),
267  Comment("prints the index of all hits associated to the track"),
268  false
269  };
271  Name("ParticleAssociations"),
272  Comment("prints the number of PF particles associated to the track"),
273  true
274  };
275 
276  }; // Config
277 
279 
280  /// Default constructor
281  explicit DumpTracks(Parameters const& config);
282 
283  /// Does the printing
284  void analyze (const art::Event& evt);
285 
286  private:
287 
288  art::InputTag fTrackModuleLabel; ///< name of module that produced the tracks
289  std::string fOutputCategory; ///< category for LogInfo output
290  unsigned int fPrintWayPoints; ///< number of printed way points
291 
292  bool fPrintNHits; ///< prints the number of associated hits
293  bool fPrintNSpacePoints; ///< prints the number of associated space points
294  bool fPrintNParticles; ///< prints the number of associated PFParticles
295  bool fPrintHits; ///< prints the index of associated hits
296  bool fPrintSpacePoints; ///< prints the index of associated space points
297  bool fPrintParticles; ///< prints the index of associated PFParticles
298 
299  /// Dumps information about the specified track
300  void DumpTrack(unsigned int iTrack, recob::Track const& track) const;
301 
302  }; // class DumpTracks
303 
304 } // namespace recob
305 
306 
307 //------------------------------------------------------------------------------
308 
309 namespace recob {
310 
311  //-------------------------------------------------
313  : EDAnalyzer (config)
314  , fTrackModuleLabel (config().TrackModuleLabel())
315  , fOutputCategory (config().OutputCategory())
316  , fPrintWayPoints (config().WayPoints())
317  , fPrintNHits (config().HitAssociations())
320  , fPrintHits (config().PrintHits())
321  , fPrintSpacePoints (config().PrintSpacePoints())
323  {}
324 
325  //-------------------------------------------------
327 
328  // fetch the data to be dumped on screen
329  auto Tracks
330  = evt.getValidHandle<std::vector<recob::Track>>(fTrackModuleLabel);
331 
333  << "The event contains " << Tracks->size() << " '"
334  << fTrackModuleLabel.encode() << "'tracks";
335 
336  std::unique_ptr<art::FindManyP<recob::Hit>> pHits(
337  fPrintNHits?
338  new art::FindManyP<recob::Hit>(Tracks, evt, fTrackModuleLabel):
339  nullptr
340  );
341  if (pHits && !pHits->isValid()) {
343  << "No hit associated with '" << fTrackModuleLabel.encode()
344  << "' tracks.\n";
345  }
346 
347  std::unique_ptr<art::FindManyP<recob::SpacePoint>> pSpacePoints(
349  new art::FindManyP<recob::SpacePoint>(Tracks, evt, fTrackModuleLabel):
350  nullptr
351  );
352  if (pSpacePoints && !pSpacePoints->isValid()) {
354  << "No space point associated with '" << fTrackModuleLabel.encode()
355  << "' tracks.\n";
356  }
357 
358  std::unique_ptr<art::FindManyP<recob::PFParticle>> pPFParticles(
360  new art::FindManyP<recob::PFParticle>(Tracks, evt, fTrackModuleLabel):
361  nullptr
362  );
363  if (pPFParticles && !pPFParticles->isValid()) {
365  << "No particle-flow particle associated with '"
366  << fTrackModuleLabel.encode() << "' tracks.\n";
367  }
368 
369  for (unsigned int iTrack = 0; iTrack < Tracks->size(); ++iTrack) {
370  const recob::Track& track = Tracks->at(iTrack);
371 
372  // print track information
373  DumpTrack(iTrack, track);
374 
376  if (pHits || pSpacePoints || pPFParticles) {
377  log << "\n associated with:";
378  if (pHits)
379  log << " " << pHits->at(iTrack).size() << " hits;";
380  if (pSpacePoints)
381  log << " " << pSpacePoints->at(iTrack).size() << " space points;";
382  if (pPFParticles)
383  log << " " << pPFParticles->at(iTrack).size() << " PF particles;";
384  } // if we have any association
385 
386  if (pHits && fPrintHits) {
387  const auto& Hits = pHits->at(iTrack);
388  log << "\n hit indices (" << Hits.size() << "):\n";
389  PrintAssociatedIndexTable(log, Hits, 10 /* 10 hits per line */, " ");
390  } // if print individual hits
391 
392  if (pSpacePoints && fPrintSpacePoints) {
393  const auto& SpacePoints = pSpacePoints->at(iTrack);
394  log << "\n space point IDs (" << SpacePoints.size() << "):\n";
395  PrintAssociatedIDTable
396  (log, SpacePoints, 10 /* 10 hits per line */, " ");
397  } // if print individual space points
398 
399  if (pPFParticles && fPrintParticles) {
400  const auto& PFParticles = pPFParticles->at(iTrack);
401  log << "\n particle indices (" << PFParticles.size() << "):\n";
402  // currently a particle has no ID
403  PrintAssociatedIndexTable
404  (log, PFParticles, 10 /* 10 hits per line */, " ");
405  } // if print individual particles
406  } // for tracks
407  } // DumpTracks::analyze()
408 
409 
410  //---------------------------------------------------------------------------
412  (unsigned int iTrack, recob::Track const& track) const
413  {
414  // print a header for the track
415  const unsigned int nPoints = track.NumberTrajectoryPoints();
417  log
418  << "Track #" << iTrack << " ID: " << track.ID()
419  << std::fixed << std::setprecision(3)
420  << " theta: " << track.Theta() << " rad, phi: " << track.Phi()
421  << " rad, length: " << track.Length() << " cm"
422  << "\n start at: ( " << track.Vertex().X()
423  << " ; " << track.Vertex().Y()
424  << " ; " << track.Vertex().Z()
425  << " ), direction: ( " << track.VertexDirection().X()
426  << " ; " << track.VertexDirection().Y()
427  << " ; " << track.VertexDirection().Z() << " )"
428  << "\n end at: ( " << track.End().X()
429  << " ; " << track.End().Y()
430  << " ; " << track.End().Z()
431  << " ), direction: ( " << track.EndDirection().X()
432  << " ; " << track.EndDirection().Y()
433  << " ; " << track.EndDirection().Z()
434  << " )"
435  << "\n with "
436  << nPoints << " trajectory points";
437 
438  if (fPrintWayPoints > 0) {
439  // print up to 10 (actually, 8 or 9) way points
440  log << "\n passes through:";
441  unsigned int skip = std::max(nPoints / fPrintWayPoints, 1U);
442  unsigned int iPoint = 0;
443  while ((iPoint += skip) < nPoints) {
444  const auto& point = track.LocationAtPoint(iPoint);
445  log << "\n [#" << iPoint << "] ("
446  << point.X() << ", " << point.Y() << ", " << point.Z()
447  << ")";
448  } // while (iPoint)
449  } // if print way points
450  } // DumpTracks::DumpTrack()
451 
452 
453  //---------------------------------------------------------------------------
455 
456 } // namespace recob
void DumpTrack(unsigned int iTrack, recob::Track const &track) const
Dumps information about the specified track.
fhicl::Atom< unsigned int > WayPoints
bool fPrintNSpacePoints
prints the number of associated space points
Reconstruction base classes.
std::string string
Definition: nybbler.cc:12
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
fhicl::Atom< std::string > OutputCategory
Point_t const & LocationAtPoint(size_t i) const
Definition: Track.h:126
struct vector vector
ChannelGroupService::Name Name
fhicl::Atom< bool > PrintHits
size_t NumberTrajectoryPoints() const
Various functions related to the presence and the number of (valid) points.
Definition: Track.h:102
Vector_t VertexDirection() const
Definition: Track.h:132
intermediate_table::const_iterator const_iterator
void analyze(const art::Event &evt)
Does the printing.
EDAnalyzer(fhicl::ParameterSet const &pset)
Definition: EDAnalyzer.h:25
std::string encode() const
Definition: InputTag.cc:97
fhicl::Atom< bool > ParticleAssociations
Q_EXPORT QTSManip setprecision(int p)
Definition: qtextstream.h:343
Configuration object.
double Phi() const
Definition: Track.h:178
double Length(size_t p=0) const
Access to various track properties.
Definition: Track.h:167
art::InputTag fTrackModuleLabel
name of module that produced the tracks
fhicl::Atom< bool > PrintSpacePoints
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
bool fPrintNHits
prints the number of associated hits
static Config * config
Definition: config.cpp:1054
double Theta() const
Access to spherical or geographical angles at vertex or at any point.
Definition: Track.h:176
fhicl::Atom< bool > SpacePointAssociations
fhicl::Atom< bool > HitAssociations
Point_t const & Vertex() const
Definition: Track.h:124
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
fhicl::Atom< art::InputTag > TrackModuleLabel
static int max(int a, int b)
size_type size() const
Definition: PtrVector.h:302
bool fPrintHits
prints the index of associated hits
Q_EXPORT QTSManip setw(int w)
Definition: qtextstream.h:331
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
art::PtrVector< recob::Hit > Hits
int ID() const
Definition: Track.h:198
Prints the content of all the tracks on screen.
Declaration of signal hit object.
#define Comment
DumpTracks(Parameters const &config)
Default constructor.
def fill(s)
Definition: translator.py:93
Vector_t EndDirection() const
Definition: Track.h:133
bool fPrintNParticles
prints the number of associated PFParticles
std::string fOutputCategory
category for LogInfo output
Provides recob::Track data product.
Point_t const & End() const
Definition: Track.h:125
TCEvent evt
Definition: DataStructs.cxx:7
bool fPrintParticles
prints the index of associated PFParticles
bool fPrintSpacePoints
prints the index of associated space points
unsigned int fPrintWayPoints
number of printed way points
Q_EXPORT QTSManip setfill(int f)
Definition: qtextstream.h:337
Definition: fwd.h:31
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
Definition: Track.h:49
QTextStream & endl(QTextStream &s)