Line data Source code
1 : ////////////////////////////////////////////////////////////////////////
2 : // Class: MissingDataCheck
3 : // Module Type: analyzer
4 : // File: MissingDataCheck_module.cc
5 : // Description: Prints out information about each event.
6 : ////////////////////////////////////////////////////////////////////////
7 :
8 : #include "art/Framework/Core/EDAnalyzer.h"
9 : #include "art/Framework/Core/ModuleMacros.h"
10 : #include "art/Framework/Principal/Event.h"
11 : #include "art/Framework/Principal/Handle.h"
12 : #include "canvas/Utilities/Exception.h"
13 :
14 : #include "artdaq-core/Data/ContainerFragment.hh"
15 : #include "artdaq-core/Data/Fragment.hh"
16 :
17 : #include <algorithm>
18 : #include <cassert>
19 : #include <cmath>
20 : #include <fstream>
21 : #include <iomanip>
22 : #include <iostream>
23 : #include <set>
24 : #include <vector>
25 :
26 : #include "art_root_io/TFileService.h"
27 :
28 : #include "TTree.h"
29 :
30 : namespace artdaq {
31 : class MissingDataCheck;
32 : }
33 :
34 : /**
35 : * \brief Check art::Event for potentially missing data
36 : */
37 : class artdaq::MissingDataCheck : public art::EDAnalyzer
38 : {
39 : public:
40 : /**
41 : * \brief MissingDataCheck Constructor
42 : * \param pset ParameterSet used to configure MissingDataCheck
43 : *
44 : * \verbatim
45 : * MissingDataCheck accepts the following Parameters:
46 : * "raw_data_label" (Default: "daq"): The label used to store artdaq data
47 : * "expected_n_fragments" (Default: -1): number of expected fragments. Uses n_frags in first event if -1
48 : * "verbosity" (Default: 0): verboseness level
49 : * \endverbatim
50 : */
51 : explicit MissingDataCheck(fhicl::ParameterSet const& pset);
52 :
53 : /**
54 : * \brief Default virtual Destructor
55 : */
56 0 : ~MissingDataCheck() override = default;
57 :
58 : /**
59 : * \brief This method is called for each art::Event in a file or run
60 : * \param e The art::Event to analyze
61 : *
62 : */
63 : void analyze(art::Event const& e) override;
64 :
65 : /**
66 : * \brief This method is called at the end of the job, used to print a summary
67 : */
68 : void endJob() override;
69 :
70 : private:
71 : MissingDataCheck(MissingDataCheck const&) = delete;
72 : MissingDataCheck(MissingDataCheck&&) = delete;
73 : MissingDataCheck& operator=(MissingDataCheck const&) = delete;
74 : MissingDataCheck& operator=(MissingDataCheck&&) = delete;
75 :
76 : std::string raw_data_label_;
77 : int expected_n_fragments_;
78 : int verbosity_;
79 : bool make_tree_;
80 :
81 : TTree* evtree_;
82 : TTree* fragtree_;
83 : unsigned int run_;
84 : unsigned int subrun_;
85 : unsigned int event_;
86 : unsigned int timeHigh_;
87 : unsigned int timeLow_;
88 :
89 : unsigned int total_n_frags_;
90 : unsigned int total_data_size_;
91 : unsigned int total_n_CFs_;
92 : unsigned int total_n_CFs_missing_;
93 : unsigned int total_n_frags_in_CFs_;
94 : unsigned int total_n_frags_broken_;
95 :
96 : unsigned int frag_id_;
97 : unsigned int seq_id_;
98 : unsigned int frag_type_;
99 : int contained_frags_;
100 : unsigned int frag_data_size_;
101 : int missing_data_;
102 : };
103 :
104 0 : artdaq::MissingDataCheck::MissingDataCheck(fhicl::ParameterSet const& pset)
105 : : EDAnalyzer(pset)
106 0 : , raw_data_label_(pset.get<std::string>("raw_data_label", "daq"))
107 0 : , expected_n_fragments_(pset.get<int>("expected_n_fragments", -1))
108 0 : , verbosity_(pset.get<int>("verbosity", 0))
109 0 : , make_tree_(pset.get<bool>("make_tree", true))
110 : {
111 0 : if (make_tree_)
112 : {
113 0 : art::ServiceHandle<art::TFileService> tfs;
114 0 : evtree_ = tfs->make<TTree>("evtree", "MissingDataCheck Event Tree");
115 0 : evtree_->Branch("run", &run_, "run/i");
116 0 : evtree_->Branch("subrun", &subrun_, "subrun/i");
117 0 : evtree_->Branch("event", &event_, "event/i");
118 0 : evtree_->Branch("timeHigh", &timeHigh_, "timeHigh/i");
119 0 : evtree_->Branch("timeLow", &timeLow_, "timeLow/i");
120 :
121 0 : evtree_->Branch("n_frag_exp", &expected_n_fragments_, "nfrag_exp/I");
122 0 : evtree_->Branch("n_frag", &total_n_frags_, "n_frag/i");
123 0 : evtree_->Branch("data_size", &total_data_size_, "data_size/i");
124 0 : evtree_->Branch("n_cont_frag", &total_n_CFs_, "n_cont_frag/i");
125 0 : evtree_->Branch("n_miss_data", &total_n_CFs_missing_, "n_miss_data/i");
126 0 : evtree_->Branch("n_frag_in_cont", &total_n_frags_in_CFs_, "n_frag_in_cont/i");
127 0 : evtree_->Branch("n_frag_broken", &total_n_frags_broken_, "n_frag_broken/i");
128 :
129 0 : fragtree_ = tfs->make<TTree>("fragtree", "MissingDataCheck Fragment Tree");
130 0 : fragtree_->Branch("run", &run_, "run/i");
131 0 : fragtree_->Branch("subrun", &subrun_, "subrun/i");
132 0 : fragtree_->Branch("event", &event_, "event/i");
133 0 : fragtree_->Branch("timeHigh", &timeHigh_, "timeHigh/i");
134 0 : fragtree_->Branch("timeLow", &timeLow_, "timeLow/i");
135 :
136 0 : fragtree_->Branch("frag_id", &frag_id_, "frag_id/i");
137 0 : fragtree_->Branch("seq_id", &seq_id_, "seq_id/i");
138 0 : fragtree_->Branch("frag_type", &frag_type_, "frag_type/i");
139 0 : fragtree_->Branch("frag_data_size", &frag_data_size_, "frag_data_size/i");
140 0 : fragtree_->Branch("contained_frags", &contained_frags_, "contained_frags/I");
141 0 : fragtree_->Branch("missing_data", &missing_data_, "missing_data/I");
142 : }
143 0 : }
144 :
145 0 : void artdaq::MissingDataCheck::analyze(art::Event const& e)
146 : {
147 0 : run_ = e.run();
148 0 : subrun_ = e.subRun();
149 0 : event_ = e.event();
150 0 : timeHigh_ = e.time().timeHigh();
151 0 : timeLow_ = e.time().timeLow();
152 :
153 : // print basic run info
154 0 : if (verbosity_ > 2)
155 : {
156 : std::cout << "Processing:"
157 0 : << " Run " << e.run()
158 0 : << ", Subrun " << e.subRun()
159 0 : << ", Event " << e.event()
160 0 : << " (Time=" << e.time().timeHigh() << " " << e.time().timeLow() << ")"
161 0 : << std::endl;
162 : }
163 :
164 : // get all the artdaq fragment collections in the event.
165 0 : std::vector<art::Handle<std::vector<artdaq::Fragment>>> fragmentHandles;
166 0 : fragmentHandles = e.getMany<std::vector<artdaq::Fragment>>();
167 :
168 : // print basic fragment number info
169 0 : if (verbosity_ > 2)
170 : {
171 0 : std::cout << "\tFound " << fragmentHandles.size() << " fragment collections." << std::endl;
172 0 : if (verbosity_ > 2)
173 : {
174 0 : for (auto const& h : fragmentHandles)
175 : {
176 0 : std::cout << "\t\tCollection " << h.provenance()->productInstanceName()
177 0 : << ":\t" << h->size() << " fragments." << std::endl;
178 : }
179 : }
180 : }
181 :
182 : // count total fragments
183 0 : total_n_frags_ = 0;
184 0 : total_data_size_ = 0;
185 0 : for (auto const& h : fragmentHandles)
186 : {
187 0 : total_n_frags_ += h->size();
188 0 : for (auto const& f : *h)
189 : {
190 0 : total_data_size_ += f.dataSizeBytes();
191 : }
192 : }
193 :
194 : // first time through, if this is -1, set it to total fragments seen
195 0 : if (expected_n_fragments_ == -1)
196 : {
197 0 : expected_n_fragments_ = total_n_frags_;
198 : }
199 :
200 0 : if (verbosity_ > 2)
201 : {
202 0 : std::cout << "\tTotal fragments = " << total_n_frags_
203 0 : << " / " << expected_n_fragments_ << std::endl;
204 0 : std::cout << "\tTotal data size in fragments = " << total_data_size_ << std::endl;
205 : }
206 : // count number of container fragments
207 0 : total_n_CFs_ = 0;
208 0 : total_n_CFs_missing_ = 0;
209 0 : total_n_frags_in_CFs_ = 0;
210 0 : total_n_frags_broken_ = 0;
211 0 : for (auto const& h : fragmentHandles)
212 : {
213 0 : std::string instance_name = h.provenance()->productInstanceName();
214 :
215 0 : if (instance_name.compare(0, 9, "Container") == 0)
216 : {
217 0 : total_n_CFs_ += h->size();
218 :
219 0 : for (auto const& f : *h)
220 : {
221 0 : artdaq::ContainerFragment cf(f);
222 0 : if (cf.missing_data())
223 : {
224 0 : ++total_n_CFs_missing_;
225 : }
226 0 : total_n_frags_in_CFs_ += cf.block_count();
227 0 : frag_id_ = f.fragmentID();
228 0 : seq_id_ = f.sequenceID();
229 0 : frag_type_ = f.type();
230 0 : contained_frags_ = cf.block_count();
231 0 : missing_data_ = cf.missing_data() ? 1 : 0;
232 0 : frag_data_size_ = f.dataSizeBytes();
233 0 : fragtree_->Fill();
234 0 : }
235 : }
236 :
237 : else
238 : {
239 0 : for (auto const& f : *h)
240 : {
241 0 : if (instance_name.compare(0, 4, "Data") == 0 ||
242 0 : instance_name.compare(0, 5, "Error") == 0 ||
243 0 : instance_name.compare(0, 6, "Broken") == 0)
244 : {
245 0 : ++total_n_frags_broken_;
246 : }
247 :
248 0 : frag_id_ = f.fragmentID();
249 0 : seq_id_ = f.sequenceID();
250 0 : frag_type_ = f.type();
251 0 : contained_frags_ = -1;
252 0 : missing_data_ = -1;
253 0 : frag_data_size_ = f.dataSizeBytes();
254 0 : fragtree_->Fill();
255 : }
256 : }
257 0 : }
258 :
259 0 : if (verbosity_ > 2)
260 : {
261 0 : std::cout << "\tTotal container fragments = " << total_n_CFs_
262 0 : << " of which " << total_n_CFs_missing_ << " have missing data."
263 0 : << std::endl;
264 0 : std::cout << "\tTotal fragments in containers = " << total_n_frags_in_CFs_ << std::endl;
265 : }
266 :
267 0 : if (make_tree_)
268 : {
269 0 : evtree_->Fill();
270 : }
271 0 : }
272 :
273 0 : void artdaq::MissingDataCheck::endJob()
274 : {
275 0 : if (verbosity_ > 0)
276 : {
277 0 : std::cout << "---------------------------------------------------" << std::endl;
278 0 : std::cout << "----------- MISSING DATA CHECK SUMMARY ------------" << std::endl;
279 0 : std::cout << "---------------------------------------------------" << std::endl;
280 :
281 0 : std::cout << "Total events processed: " << evtree_->GetEntries()
282 0 : << ", expected fragments: " << expected_n_fragments_ << std::endl;
283 :
284 : unsigned int run;
285 0 : evtree_->SetBranchAddress("run", &run);
286 : unsigned int subrun;
287 0 : evtree_->SetBranchAddress("subrun", &subrun);
288 : unsigned int event;
289 0 : evtree_->SetBranchAddress("event", &event);
290 : int n_frag_exp;
291 0 : evtree_->SetBranchAddress("n_frag_exp", &n_frag_exp);
292 : unsigned int n_frag;
293 0 : evtree_->SetBranchAddress("n_frag", &n_frag);
294 : unsigned int n_frag_broken;
295 0 : evtree_->SetBranchAddress("n_frag_broken", &n_frag_broken);
296 : unsigned int n_miss_data;
297 0 : evtree_->SetBranchAddress("n_miss_data", &n_miss_data);
298 :
299 0 : std::cout << "Events missing fragments:\t\t"
300 0 : << evtree_->GetEntries("n_frag<n_frag_exp")
301 0 : << " / " << evtree_->GetEntries() << std::endl;
302 0 : if (verbosity_ > 1)
303 : {
304 0 : if (evtree_->GetEntries("n_frag<n_frag_exp") > 0)
305 : {
306 0 : for (int i = 0; i < evtree_->GetEntries(); ++i)
307 : {
308 0 : evtree_->GetEvent(i);
309 0 : if (static_cast<int>(n_frag) < n_frag_exp)
310 : {
311 0 : std::cout << "\tEvent (" << run << "," << subrun << "," << event << ")"
312 0 : << " is missing " << n_frag_exp - n_frag << " fragments."
313 0 : << std::endl;
314 : }
315 : }
316 : }
317 : }
318 0 : std::cout << "Events with broken fragments:\t\t"
319 0 : << evtree_->GetEntries("n_frag_broken>0")
320 0 : << " / " << evtree_->GetEntries() << std::endl;
321 0 : if (evtree_->GetEntries("n_frag_broken>0") > 0)
322 : {
323 0 : for (int i = 0; i < evtree_->GetEntries(); ++i)
324 : {
325 0 : evtree_->GetEvent(i);
326 0 : if (n_frag_broken > 0)
327 : {
328 0 : std::cout << "\tEvent (" << run << "," << subrun << "," << event << ")"
329 0 : << " has " << n_frag_broken << " fragments."
330 0 : << std::endl;
331 : }
332 : }
333 : }
334 0 : std::cout << "Events missing data in fragments:\t"
335 0 : << evtree_->GetEntries("n_miss_data>0")
336 0 : << " / " << evtree_->GetEntries() << std::endl;
337 0 : if (verbosity_ > 1)
338 : {
339 0 : if (evtree_->GetEntries("n_miss_data>0") > 0)
340 : {
341 0 : for (int i = 0; i < evtree_->GetEntries(); ++i)
342 : {
343 0 : evtree_->GetEvent(i);
344 0 : if (n_miss_data > 0)
345 : {
346 0 : std::cout << "\tEvent (" << run << "," << subrun << "," << event << ")"
347 0 : << " has " << n_miss_data << " fragments missing data."
348 0 : << std::endl;
349 : }
350 : }
351 : }
352 : }
353 :
354 0 : std::cout << "---------------------------------------------------" << std::endl;
355 0 : std::cout << "---------------------------------------------------" << std::endl;
356 : }
357 0 : }
358 :
359 0 : DEFINE_ART_MODULE(artdaq::MissingDataCheck) // NOLINT(performance-unnecessary-value-param)
|