DumpClusters_module.cc
Go to the documentation of this file.
1 /**
2  * @file DumpClusters_module.cc
3  * @brief Dumps on screen the content of the clusters
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date August 13th, 2014
6  */
7 
8 // LArSoft includes
11 
12 // art libraries
18 #include "canvas/Persistency/Common/FindManyP.h"
20 
21 // support libraries
22 #include "fhiclcpp/types/Atom.h"
23 #include "fhiclcpp/types/Table.h"
24 #include "fhiclcpp/types/Name.h"
25 #include "fhiclcpp/types/Comment.h"
27 
28 // C//C++ standard libraries
29 #include <string>
30 #include <sstream>
31 #include <iomanip> // std::setw()
32 #include <algorithm> // std::min(), std::sort()
33 
34 
35 namespace recob {
36 
37  /**
38  * @brief Prints the content of all the clusters on screen
39  *
40  * This analyser prints the content of all the clusters into the
41  * LogInfo/LogVerbatim stream.
42  *
43  * Configuration parameters
44  * -------------------------
45  *
46  * - *ClusterModuleLabel* (string, _required_): input tag from the
47  * producer used to create the recob::Cluster collection to be dumped
48  * - *OutputCategory* (string, default: `"DumpClusters"`): the category
49  * used for the output (useful for filtering)
50  * - *HitsPerLine* (integer, default: `20`): the dump of hits
51  * will put this many of them for each line
52  *
53  */
54  class DumpClusters : public art::EDAnalyzer {
55  public:
56 
57  /// Configuration object
58  struct Config {
60  using Name = fhicl::Name;
61 
63  Name("ClusterModuleLabel"),
64  Comment("input tag for the clusters to be dumped")
65  };
67  Name("OutputCategory"),
68  Comment("name of the category used for message facility output"),
69  "DumpClusters"
70  };
72  Name("HitsPerLine"),
73  Comment("number of hits per line (0 suppresses hit dumping)"),
74  20U
75  };
76 
77  }; // Config
78 
80 
81  /// Default constructor
82  explicit DumpClusters(Parameters const& config);
83 
84  /// Does the printing
85  void analyze (const art::Event& evt);
86 
87  private:
88 
89  art::InputTag fClusterModuleLabel; ///< tag of the cluster data product
90  std::string fOutputCategory; ///< category for LogInfo output
91  unsigned int fHitsPerLine; ///< hits per line in the output
92 
93  }; // class DumpWires
94 
95 } // namespace recob
96 
97 
98 //------------------------------------------------------------------------------
99 namespace {
100 
101  /// Returns the length of the string representation of the specified object
102  template <typename T>
103  size_t StringLength(const T& value) {
104  std::ostringstream sstr;
105  sstr << value;
106  return sstr.str().length();
107  } // StringLength()
108 
109 } // local namespace
110 
111 namespace recob {
112 
113  //-------------------------------------------------
115  : EDAnalyzer (config)
117  , fOutputCategory (config().OutputCategory())
118  , fHitsPerLine (config().HitsPerLine())
119  {}
120 
121 
122  //-------------------------------------------------
124 
125  // fetch the data to be dumped on screen
126  art::InputTag ClusterInputTag(fClusterModuleLabel);
127 
128  auto Clusters
129  = evt.getValidHandle<std::vector<recob::Cluster>>(ClusterInputTag);
130 
131  // get cluster-hit associations
132  art::FindManyP<recob::Hit> HitAssn(Clusters, evt, ClusterInputTag);
133 
135  << "The event contains " << Clusters->size() << " '"
136  << ClusterInputTag.encode() << "' clusters";
137 
138  unsigned int iCluster = 0;
139  std::vector<size_t> HitBuffer(fHitsPerLine), LastBuffer;
140  for (const recob::Cluster& cluster: *Clusters) {
141  decltype(auto) ClusterHits = HitAssn.at(iCluster);
142 
143  // print a header for the cluster
145  << "Cluster #" << (iCluster++) << " from " << ClusterHits.size()
146  << " hits: " << cluster;
147 
148 
149  // print the hits of the cluster
150  if ((fHitsPerLine > 0) && !ClusterHits.empty()) {
151  std::vector<size_t> HitIndices;
152  for (art::Ptr<recob::Hit> pHit: ClusterHits)
153  HitIndices.push_back(pHit.key());
154  std::sort(HitIndices.begin(), HitIndices.end());
155 
156  unsigned int Padding = ::StringLength(HitIndices.back());
157 
158  mf::LogVerbatim(fOutputCategory) << " hit indices:";
159 
160  std::vector<size_t>::const_iterator iHit = HitIndices.begin(),
161  hend = HitIndices.end();
162  size_t RangeStart = *iHit, RangeStop = RangeStart;
163  std::ostringstream output_line;
164  size_t nItemsInLine = 0;
165  while (++iHit != hend) {
166 
167  if (*iHit == RangeStop + 1) {
168  ++RangeStop;
169  }
170  else {
171  // the new item does not belong to the current range:
172  // - print the current range
173  if (RangeStart == RangeStop) {
174  output_line << " " << std::setw(Padding) << RangeStart;
175  ++nItemsInLine;
176  }
177  else {
178  char fill = (RangeStart + 1 == RangeStop)? ' ': '-';
179  output_line << " " << std::setw(Padding) << RangeStart
180  << fill << fill
181  << std::setw(Padding) << std::setfill(fill) << RangeStop
182  << std::setfill(' ');
183  nItemsInLine += 2;
184  }
185  // - start a new one
186  RangeStart = RangeStop = *iHit;
187  } // if ... else
188 
189  // if we have enough stuff in the buffer, let's print it
190  if (nItemsInLine >= fHitsPerLine) {
191  nItemsInLine = 0;
192  mf::LogVerbatim(fOutputCategory) << " " << output_line.str();
193  output_line.str("");
194  }
195 
196  } // while
197 
199  line_out << " " << output_line.str();
200  if (RangeStart == RangeStop)
201  line_out << " " << std::setw(Padding) << RangeStart;
202  else {
203  char fill = (RangeStart + 1 == RangeStop)? ' ': '-';
204  line_out << " " << std::setw(Padding) << RangeStart
205  << fill << fill
206  << std::setw(Padding) << std::setfill(fill) << RangeStop;
207  }
208  } // if dumping the hits
209 
210  } // for clusters
211 
212  } // DumpClusters::analyze()
213 
215 
216 } // namespace recob
217 
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void cluster(In first, In last, Out result, Pred *pred)
Definition: NNClusters.h:41
Reconstruction base classes.
std::string string
Definition: nybbler.cc:12
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
ChannelGroupService::Name Name
Prints the content of all the clusters on screen.
Set of hits with a 2D structure.
Definition: Cluster.h:71
intermediate_table::const_iterator const_iterator
Cluster finding and building.
EDAnalyzer(fhicl::ParameterSet const &pset)
Definition: EDAnalyzer.h:25
unsigned int fHitsPerLine
hits per line in the output
std::string encode() const
Definition: InputTag.cc:97
fhicl::Atom< art::InputTag > ClusterModuleLabel
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
static Config * config
Definition: config.cpp:1054
fhicl::Atom< unsigned int > HitsPerLine
art::InputTag fClusterModuleLabel
tag of the cluster data product
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
Q_EXPORT QTSManip setw(int w)
Definition: qtextstream.h:331
fhicl::Atom< std::string > OutputCategory
Declaration of signal hit object.
#define Comment
def fill(s)
Definition: translator.py:93
void analyze(const art::Event &evt)
Does the printing.
TCEvent evt
Definition: DataStructs.cxx:7
std::string fOutputCategory
category for LogInfo output
Q_EXPORT QTSManip setfill(int f)
Definition: qtextstream.h:337
DumpClusters(Parameters const &config)
Default constructor.