00001 #include "art/Framework/Core/EDAnalyzer.h"
00002 #include "art/Framework/Principal/Handle.h"
00003 #include "art/Framework/Principal/Event.h"
00004 #include "art/Framework/Principal/Run.h"
00005 #include "art/Framework/Core/ModuleMacros.h"
00006 #include "canvas/Utilities/InputTag.h"
00007
00008 #include "artdaq-core/Data/Fragment.hh"
00009 #include "artdaq-core/Data/ContainerFragment.hh"
00010
00011 #include "artdaq-core-demo/Overlays/FragmentType.hh"
00012 #include "artdaq-core-demo/Overlays/ToyFragment.hh"
00013
00014 #include "cetlib/exception.h"
00015
00016 #include "TFile.h"
00017 #include "TRootCanvas.h"
00018 #include "TCanvas.h"
00019 #include "TGraph.h"
00020 #include "TAxis.h"
00021 #include "TH1D.h"
00022 #include "TStyle.h"
00023
00024 #include <numeric>
00025 #include <vector>
00026 #include <functional>
00027 #include <algorithm>
00028 #include <iostream>
00029 #include <sstream>
00030 #include <initializer_list>
00031 #include <limits>
00032
00033 using std::cout;
00034 using std::cerr;
00035 using std::endl;
00036
00037 namespace demo
00038 {
00042 class WFViewer : public art::EDAnalyzer
00043 {
00044 public:
00061 explicit WFViewer(fhicl::ParameterSet const& p);
00062
00066 virtual ~WFViewer() = default;
00067
00072 void analyze(art::Event const& e) override;
00073
00078 void beginRun(art::Run const&) override;
00079
00080 private:
00081
00082 std::unique_ptr<TCanvas> canvas_[2];
00083 std::vector<Double_t> x_;
00084 int prescale_;
00085 bool digital_sum_only_;
00086 art::RunNumber_t current_run_;
00087
00088 std::size_t num_x_plots_;
00089 std::size_t num_y_plots_;
00090
00091 std::string raw_data_label_;
00092 std::vector<artdaq::Fragment::fragment_id_t> fragment_ids_;
00093
00094 std::vector<std::unique_ptr<TGraph>> graphs_;
00095 std::vector<std::unique_ptr<TH1D>> histograms_;
00096
00097 std::map<artdaq::Fragment::fragment_id_t, std::size_t> id_to_index_;
00098 std::string outputFileName_;
00099 TFile* fFile_;
00100 bool writeOutput_;
00101 };
00102 }
00103
00104 demo::WFViewer::WFViewer(fhicl::ParameterSet const& ps):
00105 art::EDAnalyzer(ps)
00106 , prescale_(ps.get<int>("prescale"))
00107 , digital_sum_only_(ps.get<bool>("digital_sum_only", false))
00108 , current_run_(0)
00109 , num_x_plots_(ps.get<std::size_t>("num_x_plots", std::numeric_limits<std::size_t>::max()))
00110 , num_y_plots_(ps.get<std::size_t>("num_y_plots", std::numeric_limits<std::size_t>::max()))
00111 , raw_data_label_(ps.get<std::string>("raw_data_label", "daq"))
00112 , fragment_ids_(ps.get<std::vector<artdaq::Fragment::fragment_id_t>>("fragment_ids"))
00113 , graphs_(fragment_ids_.size())
00114 , histograms_(fragment_ids_.size())
00115 , outputFileName_(ps.get<std::string>("fileName", "artdaqdemo_onmon.root"))
00116 , writeOutput_(ps.get<bool>("write_to_file", false))
00117 {
00118 if (num_x_plots_ == std::numeric_limits<std::size_t>::max() ||
00119 num_y_plots_ == std::numeric_limits<std::size_t>::max())
00120 {
00121 switch (fragment_ids_.size())
00122 {
00123 case 1: num_x_plots_ = num_y_plots_ = 1;
00124 break;
00125 case 2: num_x_plots_ = 2;
00126 num_y_plots_ = 1;
00127 break;
00128 case 3:
00129 case 4: num_x_plots_ = 2;
00130 num_y_plots_ = 2;
00131 break;
00132 case 5:
00133 case 6: num_x_plots_ = 3;
00134 num_y_plots_ = 2;
00135 break;
00136 case 7:
00137 case 8: num_x_plots_ = 4;
00138 num_y_plots_ = 2;
00139 break;
00140 default:
00141 num_x_plots_ = num_y_plots_ = static_cast<std::size_t>(ceil(sqrt(fragment_ids_.size())));
00142 }
00143 }
00144
00145
00146
00147
00148 for (std::size_t i_f = 0; i_f < fragment_ids_.size(); ++i_f)
00149 {
00150 id_to_index_[fragment_ids_[i_f]] = i_f;
00151 }
00152
00153 gStyle->SetOptStat("irm");
00154 gStyle->SetMarkerStyle(22);
00155 gStyle->SetMarkerColor(4);
00156 }
00157
00158 void demo::WFViewer::analyze(art::Event const& e)
00159 {
00160 static std::size_t evt_cntr = -1;
00161 evt_cntr++;
00162
00163
00164
00165
00166
00167
00168 artdaq::Fragments fragments;
00169 std::vector<std::string> fragment_type_labels{"TOY1","TOY2","Container"};
00170
00171 for (auto label: fragment_type_labels)
00172 {
00173 art::Handle<artdaq::Fragments> fragments_with_label;
00174 e.getByLabel("daq", label, fragments_with_label);
00175
00176 if (!fragments_with_label.isValid()) continue;
00177
00178
00179
00180
00181 if (label == "Container")
00182 {
00183 for (auto cont : *fragments_with_label)
00184 {
00185 artdaq::ContainerFragment contf(cont);
00186 for (size_t ii = 0; ii < contf.block_count(); ++ii)
00187 {
00188 size_t fragSize = contf.fragSize(ii);
00189 artdaq::Fragment thisfrag;
00190 thisfrag.resizeBytes(fragSize);
00191
00192
00193 memcpy(thisfrag.headerAddress(), contf.at(ii), fragSize);
00194
00195
00196 fragments.push_back(thisfrag);
00197 }
00198 }
00199 }
00200 else
00201 {
00202 for (auto frag : *fragments_with_label)
00203 {
00204 fragments.emplace_back(frag);
00205 }
00206 }
00207 }
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 artdaq::Fragment::sequence_id_t expected_sequence_id = std::numeric_limits<artdaq::Fragment::sequence_id_t>::max();
00224
00225
00226 for (const auto& frag : fragments)
00227 {
00228
00229
00230
00231 std::unique_ptr<ToyFragment> toyPtr;
00232
00233
00234
00235
00236 if (expected_sequence_id == std::numeric_limits<artdaq::Fragment::sequence_id_t>::max())
00237 {
00238 expected_sequence_id = frag.sequenceID();
00239 }
00240
00241 if (expected_sequence_id != frag.sequenceID())
00242 {
00243 cerr << "Warning in WFViewer: expected fragment with sequence ID " << expected_sequence_id << ", received one with sequence ID " << frag.sequenceID() << endl;
00244 }
00245
00246 FragmentType fragtype = static_cast<FragmentType>(frag.type());
00247 std::size_t max_adc_count = std::numeric_limits<std::size_t>::max();
00248 std::size_t total_adc_values = std::numeric_limits<std::size_t>::max();
00249
00250 switch (fragtype)
00251 {
00252 case FragmentType::TOY1:
00253 toyPtr.reset(new ToyFragment(frag));
00254 total_adc_values = toyPtr->total_adc_values();
00255 max_adc_count = pow(2, frag.template metadata<ToyFragment::Metadata>()->num_adc_bits) - 1;
00256 break;
00257 case FragmentType::TOY2:
00258 toyPtr.reset(new ToyFragment(frag));
00259 total_adc_values = toyPtr->total_adc_values();
00260 max_adc_count = pow(2, frag.template metadata<ToyFragment::Metadata>()->num_adc_bits) - 1;
00261 break;
00262 default:
00263 throw cet::exception("Error in WFViewer: unknown fragment type supplied");
00264 }
00265
00266 artdaq::Fragment::fragment_id_t fragment_id = frag.fragmentID();
00267 std::size_t ind = id_to_index_[fragment_id];
00268
00269
00270
00271
00272 if (!histograms_[ind])
00273 {
00274 histograms_[ind] = std::unique_ptr<TH1D>(new TH1D(Form("Fragment_%d_hist", fragment_id), "", max_adc_count + 1, -0.5, max_adc_count + 0.5));
00275
00276 histograms_[ind]->SetTitle(Form("Frag %d, Type %s", fragment_id,
00277 fragmentTypeToString(fragtype).c_str()));
00278 histograms_[ind]->GetXaxis()->SetTitle("ADC value");
00279 }
00280
00281
00282
00283
00284
00285
00286 switch (fragtype)
00287 {
00288 case FragmentType::TOY1:
00289 case FragmentType::TOY2:
00290 for (auto val = toyPtr->dataBeginADCs(); val != toyPtr->dataEndADCs(); ++val)
00291 histograms_[ind]->Fill(*val);
00292 break;
00293
00294 default:
00295 throw cet::exception("Error in WFViewer: unknown fragment type supplied");
00296 }
00297
00298 if (evt_cntr % prescale_ - 1 && prescale_ > 1)
00299 {
00300 continue;
00301 }
00302
00303
00304
00305
00306 if (!digital_sum_only_)
00307 {
00308
00309
00310 if (x_.size() != total_adc_values)
00311 {
00312 x_.resize(total_adc_values);
00313
00314 std::iota(x_.begin(), x_.end(), 0);
00315 }
00316
00317
00318
00319
00320 if (!graphs_[ind] || static_cast<std::size_t>(graphs_[ind]->GetN()) != total_adc_values)
00321 {
00322 graphs_[ind] = std::unique_ptr<TGraph>(new TGraph(total_adc_values));
00323 graphs_[ind]->SetName(Form("Fragment_%d_graph", fragment_id));
00324 graphs_[ind]->SetLineColor(4);
00325 std::copy(x_.begin(), x_.end(), graphs_[ind]->GetX());
00326 }
00327
00328
00329
00330
00331
00332 switch (fragtype)
00333 {
00334 case FragmentType::TOY1:
00335 case FragmentType::TOY2:
00336 {
00337 std::copy(toyPtr->dataBeginADCs(), toyPtr->dataBeginADCs() + total_adc_values, graphs_[ind]->GetY());
00338 }
00339 break;
00340
00341 default:
00342 throw cet::exception("Error in WFViewer: unknown fragment type supplied");
00343 }
00344
00345
00346
00347
00348 canvas_[1]->cd(ind + 1);
00349 TVirtualPad* pad = static_cast<TVirtualPad*>(canvas_[1]->GetPad(ind + 1));
00350
00351 Double_t lo_x, hi_x, lo_y, hi_y, dummy;
00352
00353 graphs_[ind]->GetPoint(0, lo_x, dummy);
00354 graphs_[ind]->GetPoint(graphs_[ind]->GetN() - 1, hi_x, dummy);
00355
00356 lo_x -= 0.5;
00357 hi_x += 0.5;
00358
00359 lo_y = -0.5;
00360 hi_y = max_adc_count + 0.5;
00361
00362
00363 TH1F* padframe = static_cast<TH1F*>(pad->DrawFrame(lo_x, lo_y, hi_x, hi_y));
00364 padframe->SetTitle(Form("Frag %d, Type %s, SeqID %d", static_cast<int>(fragment_id),
00365 fragmentTypeToString(fragtype).c_str(),
00366 static_cast<int>(expected_sequence_id)));
00367 padframe->GetXaxis()->SetTitle("ADC #");
00368 pad->SetGrid();
00369 padframe->Draw("SAME");
00370 }
00371
00372
00373
00374 canvas_[0]->cd(ind + 1);
00375 histograms_[ind]->Draw();
00376
00377 canvas_[0]->Modified();
00378 canvas_[0]->Update();
00379
00380
00381
00382 if (!digital_sum_only_)
00383 {
00384 canvas_[1]->cd(ind + 1);
00385
00386 graphs_[ind]->Draw("PSAME");
00387
00388 canvas_[1]->Modified();
00389 canvas_[1]->Update();
00390 }
00391
00392 if (writeOutput_)
00393 {
00394 canvas_[0]->Write("wf0", TObject::kOverwrite);
00395 canvas_[1]->Write("wf1", TObject::kOverwrite);
00396 fFile_->Write();
00397 }
00398 }
00399 }
00400
00401 void demo::WFViewer::beginRun(art::Run const& e)
00402 {
00403 if (e.run() == current_run_) return;
00404 current_run_ = e.run();
00405
00406 if (writeOutput_)
00407 {
00408 fFile_ = new TFile(outputFileName_.c_str(), "RECREATE");
00409 fFile_->cd();
00410 }
00411
00412 for (int i = 0; i < 2; i++) canvas_[i] = 0;
00413 for (auto& x: graphs_) x = 0;
00414 for (auto& x: histograms_) x = 0;
00415
00416 for (int i = 0; (i < 2 && !digital_sum_only_) || i < 1; i++)
00417 {
00418 canvas_[i] = std::unique_ptr<TCanvas>(new TCanvas(Form("wf%d", i)));
00419 canvas_[i]->Divide(num_x_plots_, num_y_plots_);
00420 canvas_[i]->Update();
00421 ((TRootCanvas*)canvas_[i]->GetCanvasImp())->DontCallClose();
00422 }
00423
00424 canvas_[0]->SetTitle("ADC Value Distribution");
00425
00426 if (! digital_sum_only_)
00427 {
00428 canvas_[1]->SetTitle("ADC Values, Event Snapshot");
00429 }
00430
00431 if (writeOutput_)
00432 {
00433 canvas_[0]->Write();
00434 canvas_[1]->Write();
00435 }
00436 }
00437
00438
00439 DEFINE_ART_MODULE(demo::WFViewer)