LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
DataFlowDumper_module.cc
Go to the documentation of this file.
1 // DataFlowDumper
2 //
3 // DataFlowDumper is an output module that creates a printout of the
4 // "data flow" that produced an Event. This means it writes
5 // information naming each data product in the event, what module that
6 // product was created by, and what data products were read by that
7 // module (the 'parents' of the original data product).
8 //
9 
15 #include "fhiclcpp/types/Atom.h"
16 #include "fhiclcpp/types/Name.h"
17 
18 #include <algorithm>
19 #include <fstream>
20 #include <string>
21 #include <vector>
22 
23 namespace art {
24  // DataFlow is the class we define to provide our specialization of
25  // the ProvenanceDumper class template, to create the DataFlowDumper
26  // class.
27  class DataFlow;
29 }
30 
32 public:
33  struct Config {
34  fhicl::Atom<std::string> dotfile{fhicl::Name("dotfile"), "flow.dot"};
37  };
38 
39  explicit DataFlow(fhicl::TableFragment<Config> const& cfg);
40 
41  // Prepare to write out the graph for an event.
42  void preProcessEvent();
43 
44  // Finalize writing the graph for an event.
45  void postProcessEvent();
46 
47  // Write the graph description lines for the data product associated
48  // with the given provenance.
49  void processEventProvenance(art::Provenance const& prov);
50 
51 private:
52  std::ofstream out_;
53  int nEvents_;
54  std::string colorscheme_;
55  int debug_;
56 };
57 
58 //-----------------------------------------------------------------
59 
61  : out_(cfg().dotfile())
62  , nEvents_(0)
63  , colorscheme_(cfg().colorscheme())
64  , debug_(cfg().debuglevel())
65 {
66  if (!out_) {
68  << "Failed to create output file: " << cfg().dotfile();
69  }
70 }
71 
72 void
74 {
75  out_ << "digraph d" << nEvents_ << " {\n";
76 }
77 
78 void
80 {
81  out_ << "}\n\n";
82  ++nEvents_;
83 }
84 
85 // Write the identifier for the node for the product to which this
86 // Provenance belongs.
87 void
88 write_id(art::ProductID const pid, std::ostream& os)
89 {
90  os << "\"b" << pid << '\"';
91 }
92 
93 void
94 write_id(art::Provenance const& p, std::ostream& os)
95 {
96  write_id(p.productID(), os);
97 }
98 
99 // format_product_node defines the format for the product nade.
100 void
101 format_product_node(std::string const& fcn,
102  std::string const& pin,
103  std::ostream& os)
104 {
105  os << " [label = \"" << fcn;
106  if (!pin.empty())
107  os << "/" << pin;
108  os << "\" shape = box];\n";
109 }
110 
111 // Write the line defining the node for the product to which this
112 // Provenance belongs.
113 void
114 write_product_node(art::Provenance const& p, std::ostream& os, int debug)
115 {
116  if (debug > 0) {
117  os << "# write_product_node for provenance: " << &p << '\n';
118  }
119  write_id(p, os);
121 }
122 
123 void
124 write_product_node(art::ProductID const pid, std::ostream& os, int debug)
125 {
126  if (debug > 0) {
127  os << "# write_product_node for pid: " << pid << '\n';
128  }
129  // Access to the productList is cheap, so not really worth caching.
130  auto const& pmd = art::ProductMetaData::instance();
131  auto const& plist = pmd.productList(); // note this is a map
132  // The mapped_type in the map contains all the information we want,
133  // but we have to do a linear search through the map to find the one
134  // with the right ProductID.
135  auto it = std::find_if(begin(plist), end(plist), [&pid](auto const& keyval) {
136  return keyval.second.productID() == pid;
137  });
138  if (it == plist.end()) {
139  os << "#Missing information for product with id " << pid << '\n';
140  return;
141  }
142  write_id(pid, os);
144  it->second.friendlyClassName(), it->second.productInstanceName(), os);
145 }
146 
147 void
148 write_module_id(art::Provenance const& p, std::ostream& os)
149 {
150  os << '\"' << p.moduleLabel() << '/' << p.processName() << '\"';
151 }
152 
153 std::size_t
154 color(std::string const& procname)
155 {
156  static std::vector<std::string> names_seen;
157  auto it = std::find(begin(names_seen), end(names_seen), procname);
158  if (it == end(names_seen)) {
159  names_seen.push_back(procname);
160  return names_seen.size();
161  }
162  return std::distance(begin(names_seen), it) + 1;
163 }
164 
165 void
167  std::string const& colorscheme,
168  std::ostream& os)
169 {
170  os << " [ colorscheme=" << colorscheme << " color=" << color(p.processName())
171  << " style=filled ];\n";
172 }
173 
174 void
176  std::string const& colorscheme,
177  std::ostream& os,
178  int debug)
179 {
180  if (debug > 0) {
181  os << "# write_creator_line for provenance: " << &p << '\n';
182  }
183  write_module_id(p, os);
184  write_module_node(p, colorscheme, os);
185  write_module_id(p, os);
186  os << " -> ";
187  write_id(p, os);
188  os << ";\n";
189 }
190 
191 void
192 write_parent_id(art::ProductID const parent, std::ostream& os)
193 {
194  os << 'b' << parent;
195 }
196 
197 void
199  art::ProductID const parent,
200  std::ostream& os,
201  int debug)
202 {
203  if (debug > 0) {
204  os << "# write_parentage_line for provenance: " << &p << " parent "
205  << parent << '\n';
206  }
207  write_parent_id(parent, os);
208  os << " -> ";
209  write_module_id(p, os);
210  os << ";\n";
211 }
212 
213 void
215 {
218  for (art::ProductID const parent : p.parents()) {
219  write_parentage_line(p, parent, out_, debug_);
220  }
221 }
222 
std::vector< ProductID > const & parents() const
Definition: Provenance.h:100
fhicl::Atom< std::string > dotfile
void write_module_node(art::Provenance const &p, std::string const &colorscheme, std::ostream &os)
std::string const & productInstanceName() const
Definition: Provenance.h:73
std::string const & friendlyClassName() const
Definition: Provenance.h:63
fhicl::Atom< std::string > colorscheme
std::string const & processName() const
Definition: Provenance.h:78
std::string colorscheme_
void write_module_id(art::Provenance const &p, std::ostream &os)
void processEventProvenance(art::Provenance const &prov)
ProductID const & productID() const
Definition: Provenance.h:113
void write_product_node(art::Provenance const &p, std::ostream &os, int debug)
void write_creator_line(art::Provenance const &p, std::string const &colorscheme, std::ostream &os, int debug)
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
DebugStuff debug
Definition: DebugStruct.cxx:4
static ProductMetaData const & instance()
void write_parentage_line(art::Provenance const &p, art::ProductID const parent, std::ostream &os, int debug)
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
DataFlow(fhicl::TableFragment< Config > const &cfg)
fhicl::Atom< int > debuglevel
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::size_t color(std::string const &procname)
void write_id(art::ProductID const pid, std::ostream &os)
std::string const & moduleLabel() const
Definition: Provenance.h:68
HLT enums.
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void write_parent_id(art::ProductID const parent, std::ostream &os)
void format_product_node(std::string const &fcn, std::string const &pin, std::ostream &os)