OnMonProd_module.cc
Go to the documentation of this file.
1 ///
2 /// \file OnMonProd.cxx
3 /// \brief Top level producer module for online monitoring
4 /// \version $Id: OnMonProd.cxx,v 1.25 2012-11-27 17:57:47 mbaird42 Exp $
5 /// \author messier@indiana.edu, mbaird42@fnal.gov
6 ///
7 
8 #include <cstdlib>
9 #include <vector>
10 #include <algorithm>
11 
12 #include "TSystem.h"
13 #include "TFile.h"
14 #include "TTree.h"
18 
19 #include "NovaTimingUtilities/TimingUtilities.h"
20 #include "DAQDataFormats/RawEvent.h"
21 #include "DAQDataFormats/RawTrigger.h"
22 #include "RawData/FlatDAQData.h"
23 
42 
43 /// Online Monitoring package header
44 namespace om {
45  ///
46  /// A class that knows how to serve monitoring histograms
47  ///
48  class OnMonProdIPC : public om::IPC
49  {
50  public:
51  OnMonProdIPC(int m, const char* hdl);
52  private:
53  TH1F* FindTH1F(const char* nm);
54  TH2F* FindTH2F(const char* nm);
55  void HistoList(std::list<std::string>& hlist);
56  void AddToWatchList(int db, int dcm, int feb, int pix);
57  void RemoveFromWatchList(int db, int dcm, int feb, int pix);
58  void CurrentWatchList(std::vector<int>& db,
59  std::vector<int>& dcm,
60  std::vector<int>& feb,
61  std::vector<int>& pix);
62  };
63 
64  ///
65  /// Top level module for online monitoring
66  ///
67  class OnMonProd : public art::EDAnalyzer {
68  public:
69  explicit OnMonProd(fhicl::ParameterSet const &p);
70  virtual ~OnMonProd();
71 
72  void beginRun(const art::Run& R);
73  void beginJob();
74  void endJob();
75  void analyze(art::Event const &e);
76 
77  void reconfigure(fhicl::ParameterSet const &p);
78 
79  void NewRunNumber(unsigned int run, unsigned int subrun);
80  void NewSubrunNumber(unsigned int run, unsigned int subrun);
81 
82  bool UnpackRawDaqData(art::Event const& evt,
83  daqdataformats::RawEvent& rawevt);
84 
85  private:
86  OnMonProdIPC* fIPC; ///< Communicates with viewer
87  std::string fSHMname; ///< Shared memory for communication
88  bool fuseSHM; ///< Use SHM to communicate with a viewer?
89  unsigned int fLastRun; ///< Last run number analyzed
90  unsigned int fLastSubrun; ///< Last subrun number analyzed
91  unsigned int fPartition; ///< Partition of last event analyzed
92  bool fWriteToFile; ///< Output histogram file?
93  bool fTickerOn; ///< Turned on in the control room
94 
95  TTree* fHeader; ///< Header object to be written to disk with the histograms
96  int fFirstEvent; ///< Header: first event processed
97  int fLastEvent; ///< Header: last event processed
98  int fNevents; ///< Header: number of events processed
99 
100  unsigned long int fStartNOvATime; ///< Header: time of first processed event (in NOvA time - 64 MHz clock ticks) - initalized to -1 to make it a HUGE positive number
101  unsigned long int fEndNOvATime; ///< Header: time of last processed event (in NOvA time - 64 MHz clock ticks)
102 
103  uint32_t fStartYear; ///< Header: year of first processed event (actual years since 0 A.D.)
104  uint16_t fStartMonth; ///< Header: month of first processed event (actual month 1-12)
105  uint16_t fStartDay; ///< Header: day of first processed event (day of the month 1-31)
106  double fStartHour; ///< Header: hour of first processed event (since midnight 0.0 - 23.99999)
107 
108  uint32_t fEndYear; ///< Header: year of last processed event (actual years since 0 A.D.)
109  uint16_t fEndMonth; ///< Header: month of last processed event (actual month 1-12)
110  uint16_t fEndDay; ///< Header: day of last processed event (day of the month 1-31)
111  double fEndHour; ///< Header: hour of last processed event (since midnight 0.0 - 23.99999)
112 
113  std::vector<int> fIncompleteEvents; ///< Header: a list of incomplete events
114  };
115 }
116 
117 using namespace om;
118 
119 OnMonProdIPC::OnMonProdIPC(int m, const char* hdl) : om::IPC(m, hdl) { }
120 TH1F* OnMonProdIPC::FindTH1F(const char* nm) {
121  return HistoSet::Instance().FindTH1F(nm);
122 }
123 TH2F* OnMonProdIPC::FindTH2F(const char* nm) {
124  return HistoSet::Instance().FindTH2F(nm);
125 }
126 void OnMonProdIPC::HistoList(std::list<std::string>& hlist) {
127  HistoSet::Instance().GetNames(hlist);
128 }
129 void OnMonProdIPC::AddToWatchList(int db, int dcm, int feb, int pix) {
130  WatchListManager::Instance().Add(db, dcm, feb, pix);
131 }
132 void OnMonProdIPC::RemoveFromWatchList(int db, int dcm, int feb, int pix) {
133  WatchListManager::Instance().Remove(db, dcm, feb, pix);
134 }
135 void OnMonProdIPC::CurrentWatchList(std::vector<int>& db,
136  std::vector<int>& dcm,
137  std::vector<int>& feb,
138  std::vector<int>& pix) {
139  WatchListManager::Instance().GetList(db, dcm, feb, pix);
140 }
141 
142 //......................................................................
143 
145  EDAnalyzer(p),
146  fIPC(0),
147  fSHMname(""),
148  fuseSHM(false),
149  fLastRun(0),
150  fLastSubrun(0),
151  fPartition(4),
152  fWriteToFile(false),
153  fTickerOn(false),
154  fHeader(0),
155  fFirstEvent(1e9),
156  fLastEvent(-1),
157  fNevents(0),
158  fStartNOvATime(-1),
159  fEndNOvATime(0)
160 {
161  this->reconfigure(p);
162 
163  HistoTable::Instance(Settings::Instance().fCSVFile.c_str(),
165 
166  // Histogram fillers
167  static FEBRatesByDiblock fbdb;
168  static HitCounts hc;
169  static HitMaps hm;
170  static TQPlots tqp;
171  static WLPlots wlp;
172  static TriggerPlots trig;
173  static NanoErrors nerr;
174  static MicroErrors mcerr;
175  static DataBlockErrors dberr;
176  static RawEventErrors reerr;
177 }
178 
179 //......................................................................
180 
182 
183 //......................................................................
184 
185 //
186 // Unpack the raw DAQ data from the ART event
187 //
189  daqdataformats::RawEvent& rawevt)
190 {
191  try {
193  evt.getByLabel("daq",flatdaq_handle);
194  if (flatdaq_handle->size()!=1) {
195  std::cerr << "Required to have one and only one flat daq data object"
196  << std::endl;
197  return false;
198  }
199  rawevt.readData((*flatdaq_handle)[0].getRawBufferPointer());
200  return true;
201  }
202  catch (...) {
203  std::cerr << "arf! Bad unpack of flatdaq!" << std::endl;
204  return false;
205  }
206  return false;
207 }
208 
209 //......................................................................
210 
211 void OnMonProd::NewRunNumber(unsigned int run, unsigned int subrun)
212 {
213  if (run==0 && subrun==0) return;
214 
215  if(fWriteToFile) {
216 
217  char buff[1024];
218 
219  if(fuseSHM)
220  sprintf(buff, "%s_CR_r%.8d_s%.3d.onmon.root", fSHMname.c_str(), run, subrun);
221  else {
223  sprintf(buff, "fardet_nearline_r%.8d_s%.3d.onmon.root", run, subrun);
225  sprintf(buff, "neardet_nearline_r%.8d_s%.3d.onmon.root", run, subrun);
226  if(Settings::Instance().fDet == kNDOS)
227  sprintf(buff, "ndos_nearline_r%.8d_s%.3d.onmon.root", run, subrun);
229  sprintf(buff, "testbeam_nearline_r%.8d_s%.3d.onmon.root", run, subrun);
230  }
231 
232  std::cout << "Writing end-of-run histograms to root file "
233  << buff << "...";
234 
235  // Convert times from NOvA times to unix times.
236  // using unsigned long long rather than uint64_t to ensure consistent behavior between OSX and LINUX
237  uint16_t hour = 0;
238  uint16_t min = 0;
239  uint16_t sec = 0;
240 
241 #ifndef DARWINBUILD
242  uint64_t RoundedTime = 0.; // We need this to have > 1 second precision.
243 #else
244  unsigned long long RoundedTime = 0; // We need this to have > 1 second precision.
245 #endif
246 
250  fStartMonth, fStartYear, RoundedTime);
251 
252  fStartHour = (double)hour + (double)min/60.0 + (double)sec/3600.0
253  + (long double)(fStartNOvATime-RoundedTime)/64.0e6/3600.0;
254 
255  hour = 0;
256  min = 0;
257  sec = 0;
258  RoundedTime = 0;
262  fEndMonth, fEndYear, RoundedTime);
263 
264  fEndHour = (double)hour + (double)min/60.0 + (double)sec/3600.0
265  + (long double)(fEndNOvATime-RoundedTime)/64.0e6/3600.0;
266 
267  // Convert to "normal" time units
268  fStartYear += 1900;
269  fStartMonth += 1;
270  fEndYear += 1900;
271  fEndMonth += 1;
272 
273  // sort incomplete event numbers
274  std::sort(fIncompleteEvents.begin(),fIncompleteEvents.end());
275 
276  // Write histos and header to disk.
277  TFile* f = new TFile(buff,"RECREATE");
279  fHeader->Fill();
280  fHeader->Write("Header",TObject::kOverwrite,0);
281  f->Close();
282  delete f; f=0;
283 
284  // reset header varaibles
285  fHeader->Reset();
286  fFirstEvent = 1e9;
287  fLastEvent = -1;
288  fNevents = 0;
289  fStartNOvATime = -1;
290  fEndNOvATime = 0;
291  fIncompleteEvents.clear();
292 
293  std::cout << "done." << std::endl;
294 
295  }
296 
297 }
298 
299 //......................................................................
300 
301 void OnMonProd::NewSubrunNumber(unsigned int run, unsigned int subrun)
302 {
303  if (run==0 && subrun==0) return;
304 
305  if(fWriteToFile) {
306 
307  char buff[1024];
308 
309  if(fuseSHM)
310  sprintf(buff, "%s_CR_r%.8d_s%.3d.onmon.root", fSHMname.c_str(), run, subrun);
311  else {
313  sprintf(buff, "fardet_nearline_r%.8d_s%.3d.onmon.root", run, subrun);
315  sprintf(buff, "neardet_nearline_r%.8d_s%.3d.onmon.root", run, subrun);
316  if(Settings::Instance().fDet == kNDOS)
317  sprintf(buff, "ndos_nearline_r%.8d_s%.3d.onmon.root", run, subrun);
319  sprintf(buff, "testbeam_nearline_r%.8d_s%.3d.onmon.root", run, subrun);
320  }
321 
322  std::cout << "Writing end-of-subrun histograms to root file "
323  << buff << "...";
324 
325  // Convert times from NOvA times to unix times.
326  // using unsigned long long rather than uint64_t to ensure consistent behavior on OSX and LINUX
327  uint16_t hour = 0;
328  uint16_t min = 0;
329  uint16_t sec = 0;
330 
331 #ifndef DARWINBUILD
332  uint64_t RoundedTime = 0.; // We need this to have > 1 second precision.
333 #else
334  unsigned long long RoundedTime = 0; // We need this to have > 1 second precision.
335 #endif
336 
340  fStartMonth, fStartYear, RoundedTime);
341 
342  fStartHour = (double)hour + (double)min/60.0 + (double)sec/3600.0
343  + (long double)(fStartNOvATime-RoundedTime)/64.0e6/3600.0;
344 
345  hour = 0;
346  min = 0;
347  sec = 0;
348  RoundedTime = 0;
352  fEndMonth, fEndYear, RoundedTime);
353 
354  fEndHour = (double)hour + (double)min/60.0 + (double)sec/3600.0
355  + (long double)(fEndNOvATime-RoundedTime)/64.0e6/3600.0;
356 
357  // Convert to "normal" time units
358  fStartYear += 1900;
359  fStartMonth += 1;
360  fEndYear += 1900;
361  fEndMonth += 1;
362 
363  // sort incomplete event numbers
364  std::sort(fIncompleteEvents.begin(),fIncompleteEvents.end());
365 
366  // Write histos and header to disk.
367  TFile* f = new TFile(buff,"RECREATE");
369  fHeader->Fill();
370  fHeader->Write("Header",TObject::kOverwrite,0);
371  f->Close();
372  delete f; f=0;
373 
374  // reset header varaibles
375  fHeader->Reset();
376  fFirstEvent = 1e9;
377  fLastEvent = -1;
378  fNevents = 0;
379  fStartNOvATime = -1;
380  fEndNOvATime = 0;
381  fIncompleteEvents.clear();
382 
383  std::cout << "done." << std::endl;
384 
385  }
386 
387  std::cout << "Removing inactive WatchList items: ";
389  std::cout << "done." << std::endl;
390 
391 }
392 
393 //......................................................................
394 
396 {
397  //
398  // Define the values in the Settings object
399  //
400 
401  // try to find the correct path to the .csv file.
402  std::string filename = p.get< std::string > ("CSVFile");
403  std::string csvpath;
404  for(int i = 0; i < 4; ++i) {
405  switch(i) {
406  case 0: csvpath = "./"; break;
407  case 1: csvpath = "./util/"; break;
408  case 2:
409  csvpath = getenv("SRT_PRIVATE_CONTEXT");
410  csvpath += "/OnlineMonitoring/util/";
411  break;
412  case 3:
413  csvpath = getenv("SRT_PUBLIC_CONTEXT");
414  csvpath += "/OnlineMonitoring/util/";
415  break;
416  }
417  csvpath += filename;
418  if(access(csvpath.c_str(), F_OK) != -1) {
419  Settings::Instance().fCSVFile = csvpath;
420  break;
421  }
422  } // end for i
423 
424  std::string d = p.get< std::string > ("Detector");
425  if (d == "NDOS") Settings::Instance().fDet = kNDOS;
426  else if (d == "ND") Settings::Instance().fDet = kNEARDET;
427  else if (d == "FD") Settings::Instance().fDet = kFARDET;
428  else if (d == "TB") Settings::Instance().fDet = kTESTBEAM;
429  else abort();
430 
431  fSHMname = p.get<std::string>("SHMHandle");
432  fuseSHM = p.get<bool >("useSHM");
433 
434  if (fIPC) delete fIPC;
435  if (fuseSHM) fIPC = new OnMonProdIPC(kIPC_SERVER, fSHMname.c_str());
436 
437  bool debug = p.get< bool > ("Debug");
439 
440  fWriteToFile = p.get<bool>("WriteToFile");
441  fTickerOn = p.get<bool>("TickerOn");
442 }
443 
444 
445 //......................................................................
446 
448 
449 //......................................................................
450 
452 {
453  if(fHeader) { delete fHeader; fHeader = 0; }
454  fHeader = new TTree("Header","Header Information");
455 
456  fHeader->Branch("Run",&fLastRun);
457  fHeader->Branch("Subrun",&fLastSubrun);
458  fHeader->Branch("Partition",&fPartition);
459  fHeader->Branch("FirstEvent",&fFirstEvent);
460  fHeader->Branch("LastEvent",&fLastEvent);
461  fHeader->Branch("Nevents",&fNevents);
462  fHeader->Branch("StartYear",&fStartYear);
463  fHeader->Branch("StartMonth",&fStartMonth);
464  fHeader->Branch("StartDay",&fStartDay);
465  fHeader->Branch("StartHour",&fStartHour);
466  fHeader->Branch("EndYear",&fEndYear);
467  fHeader->Branch("EndMonth",&fEndMonth);
468  fHeader->Branch("EndDay",&fEndDay);
469  fHeader->Branch("EndHour",&fEndHour);
470  fHeader->Branch("IncompleteEvents",&fIncompleteEvents);
471 
472  // I would like to add these two variables to the header object but
473  // root complains that an unsigned long int is an unacceptable type.
474  //
475  // fHeader->Branch("StartNovaTime", &fStartNOvATime);
476  // fHeader->Branch("EndNovaTime", &fEndNOvATime);
477 }
478 
479 //......................................................................
480 
482 {
483  if(Settings::Instance().fDet != kFARDET)
485  if(Settings::Instance().fDet == kFARDET)
487  if(fIPC) { delete fIPC; fIPC = 0; }
488  if(fHeader) { delete fHeader; fHeader = 0; }
489 }
490 
491 //......................................................................
492 
494 {
495  bool aok;
496 
497  //
498  // Handle any pending requests for histograms
499  //
500  if (fuseSHM) fIPC->HandleRequests();
501 
502  static daqdataformats::RawEvent rawevt;
503  aok = this->UnpackRawDaqData(evt, rawevt);
504  if (aok==false) return;
505 
506  unsigned int run = rawevt.getRunNumber();
507  unsigned int subrun = rawevt.getSubrun();
508  unsigned int event = rawevt.getEventNumber();
509  unsigned int partition = rawevt.getPartition();
510  unsigned long int time = rawevt.getTrigger()->getTriggerStart();
511 
512 
513 
514  //
515  // Check if the run/subrun number has changed
516  //
517  if ( (subrun != fLastSubrun) && (Settings::Instance().fDet != kFARDET) ) {
519  }
520  if ( (run != fLastRun) && (Settings::Instance().fDet == kFARDET) ) {
522  }
523 
524  //
525  // update Header variables.
526  //
527  fNevents++;
528  fLastRun = run;
531 
532  // first/last event are not necessarily coorelated with earliest/latest time
533  if(time < fStartNOvATime)
535  if((int)event < fFirstEvent)
536  fFirstEvent = event;
537  if(time > fEndNOvATime)
538  fEndNOvATime = time;
539  if((int)event > fLastEvent)
540  fLastEvent = event;
541 
542  if( rawevt.getHeader()->isEventIncomplete() ) {
543  fIncompleteEvents.push_back(event);
544  }
545 
546 
547 
548 
549  static unsigned int count = 0;
550  if (++count%10==0) {
551  if (fuseSHM) fIPC->PostResources(run, subrun, event);
552  std::cout << "onmon_prod: run/sub/evt="
553  << run << "/" << subrun << "/" << event << " "
554  << " type:size="
555  << rawevt.getEventType() << ":"
556  << rawevt.getEventSize()
557  << std::endl;
558  }
559 
560  //
561  // Update the ticker so it can notify its subscribers.
562  // Do this BEFORE unpacking so that there are no overlaps in plots
563  // reset every 24 hours.
564  //
565  if (fTickerOn) Ticker::Instance().Update(run, subrun);
566 
567  //
568  // Unpack the raw event and publish results to plot-making
569  // subscribers
570  //
572 }
573 
574 ////////////////////////////////////////////////////////////////////////
575 
576 
std::string fCSVFile
Definition: Settings.h:17
std::vector< int > fIncompleteEvents
Header: a list of incomplete events.
void analyze(art::Event const &e)
uint16_t fEndDay
Header: day of last processed event (day of the month 1-31)
bool UnpackRawDaqData(art::Event const &evt, daqdataformats::RawEvent &rawevt)
Unpack the DAQ data, prepare summaries, and post data.
OnMonProd(fhicl::ParameterSet const &p)
TH1F * FindTH1F(const char *nm)
Definition: HistoSet.cxx:50
void PostResources(unsigned int run, unsigned int subrun, unsigned int event)
Definition: IPC.cxx:528
Class to manage the shared memory segment.
std::string fSHMname
Shared memory for communication.
int fLastEvent
Header: last event processed.
void Remove(int db, int dcm, int feb, int pix)
const char * p
Definition: xmltok.h:285
void AddToWatchList(int db, int dcm, int feb, int pix)
void WriteToRootFile(TFile *f)
Definition: HistoSet.cxx:129
static constexpr Double_t nm
Definition: Munits.h:133
struct IPCBlock * fIPC
Pointer to struct.
Definition: IPC.h:151
bool fWriteToFile
Output histogram file?
void SetDebug(bool debug)
OStream cerr
Definition: OStream.cxx:7
void Update(unsigned int run, unsigned int subrun)
Definition: Ticker.cxx:34
string filename
Definition: shutoffs.py:106
void GetList(std::vector< int > &db, std::vector< int > &dcm, std::vector< int > &feb, std::vector< int > &pix)
DEFINE_ART_MODULE(TestTMapFile)
bool convertNovaTimeToUnixTime(uint64_t const &inputNovaTime, struct timespec &outputUnixTime)
::xsd::cxx::tree::time< char, simple_type > time
Definition: Database.h:194
void CurrentWatchList(std::vector< int > &db, std::vector< int > &dcm, std::vector< int > &feb, std::vector< int > &pix)
Definition: Run.h:31
unsigned int fPartition
Partition of last event analyzed.
void NewRunNumber(unsigned int run, unsigned int subrun)
unsigned int fLastSubrun
Last subrun number analyzed.
TTree * fHeader
Header object to be written to disk with the histograms.
int fNevents
Header: number of events processed.
static const int kIPC_SERVER
Definition: IPC.h:23
Class to read, hold, and deliver histogram data.
void Add(int db, int dcm, int feb, int pix)
Detector_t fDet
Definition: Settings.h:18
int HandleRequests()
Definition: IPC.cxx:516
void NewSubrunNumber(unsigned int run, unsigned int subrun)
void RemoveFromWatchList(int db, int dcm, int feb, int pix)
void beginJob()
double fStartHour
Header: hour of first processed event (since midnight 0.0 - 23.99999)
void UnpackRawEvent(daqdataformats::RawEvent &rawevt)
std::string getenv(std::string const &name)
T get(std::string const &key) const
Definition: ParameterSet.h:231
double fEndHour
Header: hour of last processed event (since midnight 0.0 - 23.99999)
int evt
Notify subscribers when certain time/event intervals have elapsed.
Float_t d
Definition: plot.C:236
#define R(x)
void beginRun(const art::Run &R)
unsigned long int fStartNOvATime
Header: time of first processed event (in NOvA time - 64 MHz clock ticks) - initalized to -1 to make ...
A simple object that conatins all the global settings.
void HistoList(std::list< std::string > &hlist)
Definition: run.py:1
static Ticker & Instance()
Definition: Ticker.cxx:26
OStream cout
Definition: OStream.cxx:6
static float min(const float a, const float b, const float c)
Definition: absgeo.cxx:45
uint32_t fStartYear
Header: year of first processed event (actual years since 0 A.D.)
::xsd::cxx::tree::string< char, simple_type > string
Definition: Database.h:154
Definition: IPC.h:29
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
int fFirstEvent
Header: first event processed.
uint16_t fStartMonth
Header: month of first processed event (actual month 1-12)
virtual ~OnMonProd()
uint16_t fStartDay
Header: day of first processed event (day of the month 1-31)
unsigned int fLastRun
Last run number analyzed.
static RawEventUnpacker & Instance()
void reconfigure(fhicl::ParameterSet const &p)
bool fTickerOn
Turned on in the control room.
static WatchListManager & Instance()
TH1F * FindTH1F(const char *nm)
TH2F * FindTH2F(const char *nm)
Definition: HistoSet.cxx:59
OnMonProdIPC(int m, const char *hdl)
static HistoSet & Instance()
Definition: HistoSet.cxx:24
static HistoTable & Instance(const char *f=0, Detector_t d=kALLDET)
Definition: HistoTable.cxx:21
Float_t e
Definition: plot.C:35
OnMonProdIPC * fIPC
Communicates with viewer.
Hold the collection of histograms created by the producer.
uint32_t fEndYear
Header: year of last processed event (actual years since 0 A.D.)
unsigned long int fEndNOvATime
Header: time of last processed event (in NOvA time - 64 MHz clock ticks)
static Settings & Instance()
Definition: Settings.cxx:12
void GetNames(std::list< std::string > &h)
Definition: HistoSet.cxx:111
Online Monitoring package header.
bool fuseSHM
Use SHM to communicate with a viewer?
uint16_t fEndMonth
Header: month of last processed event (actual month 1-12)
bool convertUnixTimeToNovaTime(struct timespec const &inputUnixTime, uint64_t &outputNovaTime)
TH2F * FindTH2F(const char *nm)