$treeview $search $mathjax $extrastylesheet
artdaq_demo
v3_04_01
$projectbrief
|
$projectbrief
|
$searchbox |
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_except/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 // id_to_index_ will translate between a fragment's ID and where in 00146 // the vector of graphs and histograms it's located 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 // John F., 1/22/14 -- there's probably a more elegant way of 00164 // collecting fragments of various types using ART interface code; 00165 // will investigate. Right now, we're actually re-creating the 00166 // fragments locally 00167 00168 artdaq::Fragments fragments; 00169 artdaq::FragmentPtrs containerFragments; 00170 std::vector<std::string> fragment_type_labels{"TOY1","TOY2","ContainerTOY1", "ContainerTOY2"}; 00171 00172 for (auto label: fragment_type_labels) 00173 { 00174 art::Handle<artdaq::Fragments> fragments_with_label; 00175 e.getByLabel("daq", label, fragments_with_label); 00176 00177 if (!fragments_with_label.isValid()) continue; 00178 // for (int i_l = 0; i_l < static_cast<int>(fragments_with_label->size()); ++i_l) { 00179 // fragments.emplace_back( (*fragments_with_label)[i_l] ); 00180 // } 00181 00182 if (label == "Container" || label == "ContainerTOY1" || label == "ContainerTOY2") 00183 { 00184 for (auto cont : *fragments_with_label) 00185 { 00186 artdaq::ContainerFragment contf(cont); 00187 for (size_t ii = 0; ii < contf.block_count(); ++ii) 00188 { 00189 containerFragments.push_back(contf[ii]); 00190 fragments.push_back(*containerFragments.back()); 00191 } 00192 } 00193 } 00194 else 00195 { 00196 for (auto frag : *fragments_with_label) 00197 { 00198 fragments.emplace_back(frag); 00199 } 00200 } 00201 } 00202 00203 // John F., 1/5/14 00204 00205 // Here, we loop over the fragments passed to the analyze 00206 // function. A warning is flashed if either (A) the fragments aren't 00207 // all from the same event, or (B) there's an unexpected number of 00208 // fragments given the number of boardreaders and the number of 00209 // fragments per board 00210 00211 // For every Nth event, where N is the "prescale" setting, plot the 00212 // distribution of ADC counts from each board_id / fragment_id 00213 // combo. Also, if "digital_sum_only" is set to false in the FHiCL 00214 // string, then plot, for the Nth event, a graph of the ADC values 00215 // across all channels in each board_id / fragment_id combo 00216 00217 artdaq::Fragment::sequence_id_t expected_sequence_id = std::numeric_limits<artdaq::Fragment::sequence_id_t>::max(); 00218 00219 // for (std::size_t i = 0; i < fragments.size(); ++i) { 00220 for (const auto& frag : fragments) 00221 { 00222 // Pointers to the types of fragment overlays WFViewer can handle; 00223 // only one will be used per fragment, of course 00224 00225 std::unique_ptr<ToyFragment> toyPtr; 00226 00227 // const auto& frag( fragments[i] ); // Basically a shorthand 00228 00229 // if (i == 0) 00230 if (expected_sequence_id == std::numeric_limits<artdaq::Fragment::sequence_id_t>::max()) 00231 { 00232 expected_sequence_id = frag.sequenceID(); 00233 } 00234 00235 if (expected_sequence_id != frag.sequenceID()) 00236 { 00237 cerr << "Warning in WFViewer: expected fragment with sequence ID " << expected_sequence_id << ", received one with sequence ID " << frag.sequenceID() << endl; 00238 } 00239 00240 FragmentType fragtype = static_cast<FragmentType>(frag.type()); 00241 std::size_t max_adc_count = std::numeric_limits<std::size_t>::max(); 00242 std::size_t total_adc_values = std::numeric_limits<std::size_t>::max(); 00243 00244 switch (fragtype) 00245 { 00246 case FragmentType::TOY1: 00247 toyPtr.reset(new ToyFragment(frag)); 00248 total_adc_values = toyPtr->total_adc_values(); 00249 max_adc_count = pow(2, frag.template metadata<ToyFragment::Metadata>()->num_adc_bits) - 1; 00250 break; 00251 case FragmentType::TOY2: 00252 toyPtr.reset(new ToyFragment(frag)); 00253 total_adc_values = toyPtr->total_adc_values(); 00254 max_adc_count = pow(2, frag.template metadata<ToyFragment::Metadata>()->num_adc_bits) - 1; 00255 break; 00256 default: 00257 throw cet::exception("Error in WFViewer: unknown fragment type supplied"); 00258 } 00259 00260 artdaq::Fragment::fragment_id_t fragment_id = frag.fragmentID(); 00261 if (!id_to_index_.count(fragment_id)) 00262 { 00263 cerr << "Warning in WFViewer: unexpected Fragment with fragment_id " << std::to_string(fragment_id) << " encountered!"; 00264 continue; 00265 } 00266 std::size_t ind = id_to_index_[fragment_id]; 00267 00268 00269 // If a histogram doesn't exist for this board_id / fragment_id combo, create it 00270 00271 if (!histograms_[ind]) 00272 { 00273 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)); 00274 00275 histograms_[ind]->SetTitle(Form("Frag %d, Type %s", fragment_id, 00276 fragmentTypeToString(fragtype).c_str())); 00277 histograms_[ind]->GetXaxis()->SetTitle("ADC value"); 00278 } 00279 00280 // For every event, fill the histogram (prescale is ignored here) 00281 00282 // Is there some way to templatize an ART module? If not, we're 00283 // stuck with this switch code... 00284 00285 switch (fragtype) 00286 { 00287 case FragmentType::TOY1: 00288 case FragmentType::TOY2: 00289 for (auto val = toyPtr->dataBeginADCs(); val != toyPtr->dataEndADCs(); ++val) 00290 histograms_[ind]->Fill(*val); 00291 break; 00292 00293 default: 00294 throw cet::exception("Error in WFViewer: unknown fragment type supplied"); 00295 } 00296 00297 if (evt_cntr % prescale_ - 1 && prescale_ > 1) 00298 { 00299 continue; 00300 } 00301 00302 // If we pass the prescale, then if we're not going with 00303 // digital_sum_only, plot the ADC counts for this particular event/board/fragment_id 00304 00305 if (!digital_sum_only_) 00306 { 00307 // Create the graph's x-axis 00308 00309 if (x_.size() != total_adc_values) 00310 { 00311 x_.resize(total_adc_values); 00312 00313 std::iota(x_.begin(), x_.end(), 0); 00314 } 00315 00316 // If the graph doesn't exist, create it. Not sure whether to 00317 // make it an error if the total_adc_values is new 00318 00319 if (!graphs_[ind] || static_cast<std::size_t>(graphs_[ind]->GetN()) != total_adc_values) 00320 { 00321 graphs_[ind] = std::unique_ptr<TGraph>(new TGraph(total_adc_values)); 00322 graphs_[ind]->SetName(Form("Fragment_%d_graph", fragment_id)); 00323 graphs_[ind]->SetLineColor(4); 00324 std::copy(x_.begin(), x_.end(), graphs_[ind]->GetX()); 00325 } 00326 00327 // Get the data from the fragment 00328 00329 // Is there some way to templatize an ART module? If not, we're stuck with this awkward switch code... 00330 00331 switch (fragtype) 00332 { 00333 case FragmentType::TOY1: 00334 case FragmentType::TOY2: 00335 { 00336 std::copy(toyPtr->dataBeginADCs(), toyPtr->dataBeginADCs() + total_adc_values, graphs_[ind]->GetY()); 00337 } 00338 break; 00339 00340 default: 00341 throw cet::exception("Error in WFViewer: unknown fragment type supplied"); 00342 } 00343 00344 00345 // And now prepare the graphics without actually drawing anything yet 00346 00347 canvas_[1]->cd(ind + 1); 00348 TVirtualPad* pad = static_cast<TVirtualPad*>(canvas_[1]->GetPad(ind + 1)); 00349 00350 Double_t lo_x, hi_x, lo_y, hi_y, dummy; 00351 00352 graphs_[ind]->GetPoint(0, lo_x, dummy); 00353 graphs_[ind]->GetPoint(graphs_[ind]->GetN() - 1, hi_x, dummy); 00354 00355 lo_x -= 0.5; 00356 hi_x += 0.5; 00357 00358 lo_y = -0.5; 00359 hi_y = max_adc_count + 0.5; 00360 00361 00362 TH1F* padframe = static_cast<TH1F*>(pad->DrawFrame(lo_x, lo_y, hi_x, hi_y)); 00363 padframe->SetTitle(Form("Frag %d, Type %s, SeqID %d", static_cast<int>(fragment_id), 00364 fragmentTypeToString(fragtype).c_str(), 00365 static_cast<int>(expected_sequence_id))); 00366 padframe->GetXaxis()->SetTitle("ADC #"); 00367 pad->SetGrid(); 00368 padframe->Draw("SAME"); 00369 } 00370 00371 // Draw the histogram 00372 00373 canvas_[0]->cd(ind + 1); 00374 histograms_[ind]->Draw(); 00375 00376 canvas_[0]->Modified(); 00377 canvas_[0]->Update(); 00378 00379 // And, if desired, the Nth event's ADC counts 00380 00381 if (!digital_sum_only_) 00382 { 00383 canvas_[1]->cd(ind + 1); 00384 00385 graphs_[ind]->Draw("PSAME"); 00386 00387 canvas_[1]->Modified(); 00388 canvas_[1]->Update(); 00389 } 00390 00391 if (writeOutput_) 00392 { 00393 canvas_[0]->Write("wf0", TObject::kOverwrite); 00394 canvas_[1]->Write("wf1", TObject::kOverwrite); 00395 fFile_->Write(); 00396 } 00397 } 00398 } 00399 00400 void demo::WFViewer::beginRun(art::Run const& e) 00401 { 00402 if (e.run() == current_run_) return; 00403 current_run_ = e.run(); 00404 00405 if (writeOutput_) 00406 { 00407 fFile_ = new TFile(outputFileName_.c_str(), "RECREATE"); 00408 fFile_->cd(); 00409 } 00410 00411 for (int i = 0; i < 2; i++) canvas_[i] = 0; 00412 for (auto& x: graphs_) x = 0; 00413 for (auto& x: histograms_) x = 0; 00414 00415 for (int i = 0; (i < 2 && !digital_sum_only_) || i < 1; i++) 00416 { 00417 canvas_[i] = std::unique_ptr<TCanvas>(new TCanvas(Form("wf%d", i))); 00418 canvas_[i]->Divide(num_x_plots_, num_y_plots_); 00419 canvas_[i]->Update(); 00420 ((TRootCanvas*)canvas_[i]->GetCanvasImp())->DontCallClose(); 00421 } 00422 00423 canvas_[0]->SetTitle("ADC Value Distribution"); 00424 00425 if (! digital_sum_only_) 00426 { 00427 canvas_[1]->SetTitle("ADC Values, Event Snapshot"); 00428 } 00429 00430 if (writeOutput_) 00431 { 00432 canvas_[0]->Write(); 00433 canvas_[1]->Write(); 00434 } 00435 } 00436 00437 00438 DEFINE_ART_MODULE(demo::WFViewer)