9 #include "art/Framework/Core/EDAnalyzer.h"
10 #include "art/Framework/Core/ModuleMacros.h"
11 #include "art/Framework/Principal/Event.h"
12 #include "art/Framework/Principal/Handle.h"
13 #include "art/Framework/Principal/Run.h"
16 #include "artdaq-core/Data/ContainerFragment.hh"
17 #include "artdaq-core/Data/Fragment.hh"
18 #include "artdaq-core-mu2e/Data/CRVDataDecoder.hh"
19 #include "artdaq-core-mu2e/Overlays/DTCEventFragment.hh"
20 #include "artdaq-core-mu2e/Overlays/FragmentType.hh"
25 #include "THttpServer.h"
29 #include "CrvDQMStyle.hh"
33 class CrvDQM :
public art::EDAnalyzer {
36 explicit CrvDQM(fhicl::ParameterSet
const& ps);
43 void beginJob()
override;
44 void analyze(art::Event
const& e)
override;
45 void endJob()
override;
50 float onlineRefreshPeriod_;
52 int keepAliveDuration_;
53 std::string histColor_;
57 std::unordered_map<std::string, TH1D*> hists_;
59 std::chrono::time_point<std::chrono::steady_clock> lastUpdate_;
60 std::size_t eventCounter_;
61 std::thread keepAliveThread_;
66 CrvDQM::CrvDQM(fhicl::ParameterSet
const& ps)
68 , port_(ps.get<int>(
"port", 8877))
69 , diagLevel_(ps.get<int>(
"diagLevel", 1))
70 , onlineRefreshPeriod_(ps.get<float> (
"onlineRefreshPeriod", 500))
71 , keepAlive_(ps.get<int> (
"keepAlive", true))
72 , keepAliveDuration_(ps.get<int> (
"keepAliveDuration", 5))
73 , histColor_(ps.get<std::string> (
"histColor",
"blue"))
82 if(keepAliveThread_.joinable()) {
83 keepAliveThread_.join();
94 for (
auto& hist : hists_) {
95 if (hist.second)
delete hist.second;
96 hist.second =
nullptr;
101 void CrvDQM::beginJob() {
103 server_ =
new THttpServer(Form(
"http:%d", port_));
106 CrvDQMStyle::SetStyle();
109 std::string canvasName =
"WebDisplay";
110 canvas_ =
new TCanvas(canvasName.c_str(),
"CRV web display");
111 canvas_->Divide(2,2);
114 hists_[
"channels"] =
new TH1D(
"Channels",
";Channel;Counts", 64, -0.5, 63.5);
115 hists_[
"timestamps"] =
new TH1D(
"Timestamps",
";Timestamp;Counts", 256, 0, 255);
116 hists_[
"nhits"] =
new TH1D(
"Hits",
";Hits / block;Counts", 61, 0, 60);
117 hists_[
"adc"] =
new TH1D(
"ADC",
";ADC;Counts", 201, -100, 100);
121 for (
auto& hist : hists_) {
123 canvas_->cd(canvasIdx);
126 CrvDQMStyle::FormatHist(hist.second, histColor_);
132 server_->Register(
"/", canvas_);
135 server_->SetItemField(
"/",
"_monitoring", Form(
"%f", onlineRefreshPeriod_));
136 server_->SetItemField(
"/",
"_sidebar",
"0");
137 server_->SetItemField(
"/",
"_drawitem", canvasName.c_str());
138 server_->SetItemField(
"/",
"_http_cache",
"0");
141 lastUpdate_ = std::chrono::steady_clock::now();
144 printf(
"Server running on http://localhost:%d/\n", port_);
147 keepAliveThread_ = std::thread([
this]() {
149 gSystem->ProcessEvents();
150 std::this_thread::sleep_for(std::chrono::milliseconds(100));
156 void CrvDQM::analyze(art::Event
const& e) {
158 std::vector<art::Handle<artdaq::Fragments> > fragmentHandles;
159 fragmentHandles = e.getMany<std::vector<artdaq::Fragment> >();
160 artdaq::FragmentPtrs containerFragments;
161 artdaq::Fragments fragments;
164 for (
const auto& handle : fragmentHandles) {
166 if (!handle.isValid() || handle->empty()) {
173 if (handle->front().type() == artdaq::Fragment::ContainerFragmentType) {
175 for (
const auto& cont : *handle) {
176 artdaq::ContainerFragment contf(cont);
178 if (contf.fragment_type() != mu2e::FragmentType::DTCEVT) {
182 for (
size_t i = 0; i < contf.block_count(); ++i) {
183 containerFragments.push_back(contf[i]);
184 fragments.push_back(*containerFragments.back());
188 if (handle->front().type() == mu2e::FragmentType::DTCEVT) {
190 for (
auto frag : *handle) {
191 fragments.emplace_back(frag);
196 if (diagLevel_ > 1) {
197 TLOG(TLVL_INFO) <<
"[CrvDQM::analyze] Found nFragments" << fragments.size();
201 for (
const auto& frag : fragments) {
203 mu2e::DTCEventFragment bb(frag);
204 auto data = bb.getData();
206 if (diagLevel_ > 1) {
207 TLOG(TLVL_INFO) <<
"Event tag:\t" <<
"0x" << std::hex << std::setw(4) << std::setfill(
'0') <<
event->GetEventWindowTag().GetEventWindowTag(
true);
209 DTCLib::DTC_EventHeader* eventHeader =
event->GetHeader();
211 if (diagLevel_ > 1) {
212 TLOG(TLVL_INFO) << eventHeader->toJson() << std::endl
213 <<
"Subevents count: " <<
event->GetSubEventCount() << std::endl;
216 bool plotsUpdated =
false;
217 for (
unsigned int i = 0; i <
event->GetSubEventCount(); ++i) {
218 DTCLib::DTC_SubEvent& subevent = *(
event->GetSubEvent(i));
219 if (diagLevel_ > 1) {
220 TLOG(TLVL_INFO) <<
"Subevent [" << i <<
"]:" << std::endl;
221 TLOG(TLVL_INFO) << subevent.GetHeader()->toJson() << std::endl;
222 TLOG(TLVL_INFO) <<
"Number of Data Block: " << subevent.GetDataBlockCount() << std::endl;
225 for (
size_t bl = 0; bl < subevent.GetDataBlockCount(); ++bl) {
227 auto block = subevent.GetDataBlock(bl);
228 auto blockheader = block->GetHeader();
229 if (diagLevel_ > 1) {
230 TLOG(TLVL_INFO) << blockheader->toJSON() << std::endl;
231 for (
int ii = 0; ii < blockheader->GetPacketCount(); ++ii) {
232 TLOG(TLVL_INFO) << DTCLib::DTC_DataPacket(((uint8_t*)block->blockPointer) + ((ii + 1) * 16)).toJSON() << std::endl;
237 if(blockheader->GetSubsystem() == 0x2) {
238 if(blockheader->isValid()) {
240 if( blockheader->GetVersion() == 0x0 ) {
241 auto crvData = mu2e::CRVDataDecoder(subevent);
243 auto hits = crvData.GetCRVHits(bl);
244 for (
auto& hit : hits) {
246 hists_[
"channels"]->Fill(hit.first.febChannel);
247 hists_[
"timestamps"]->Fill(hit.first.HitTime);
248 for (
auto& adc : hit.second) {
249 hists_[
"adc"]->Fill(adc.ADC);
252 hists_[
"nhits"]->Fill(hits.size());
265 auto currentTime = std::chrono::steady_clock::now();
266 std::chrono::duration<double, std::milli> elapsed = currentTime - lastUpdate_;
267 if(elapsed.count() >= onlineRefreshPeriod_) {
269 for (
auto& hist : hists_) {
270 double maxContent = hist.second->GetBinContent(hist.second->GetMaximumBin());
271 hist.second->GetYaxis()->SetRangeUser(0, 1.15*maxContent);
276 gSystem->ProcessEvents();
277 lastUpdate_ = currentTime;
282 catch (
const std::exception& e) {
283 if (diagLevel_ > 0) {
284 TLOG(TLVL_WARNING) <<
"Error processing fragment: " << e.what();
292 void CrvDQM::endJob() {
294 printf(
"========================================\n");
295 printf(
"Processed Events : %zu\n", eventCounter_);
301 printf(
"Keeping server alive for %i minutes", keepAliveDuration_);
302 printf(
"\n========================================\n");
303 std::this_thread::sleep_for(std::chrono::minutes(keepAliveDuration_));
305 printf(
"Killing server");
306 printf(
"\n========================================\n");
311 DEFINE_ART_MODULE(CrvDQM)