Details of the producer

(See the general overview section for specifics on how to run the producer.)

Structure of the Producer

Producer classes

The structure of the producer can be divided into three different groups of classes as outlined below.

Main "working" classes:
  • OnMonProd - This is the top level ART analyzer module that receives and unpacks the event data from the FlatDAQData object
  • RawEventUnpacker - This class "unpacks" the FlatDAQData spooling through the DataBlocks, MicroSlices, and NanoSlices. As it spools through the data it prepares summaries of the data for histogram makers
Summary classes that store the raw information:
  • RawEventSummary - An ntuple-style summary of the event overall
  • DataBlockSummary - An ntuple-style summary of an entire data block
  • MicroSliceSummary - An ntuple-style summary of an entire micro slice
  • NanoSliceSummary - An ntuple-style summary of a nano-slice
Histogram makers:
  • RawEventErrors - Fills histograms with errors and alerts reported at the event level
  • DataBlockErrors - Fills histograms with errors and alerts reported at the data block level
  • MicroErrors - Fills histograms with errors and alerts reported at the micro-slice level
  • NanoErrors - Fills histograms with errors and alerts reported at the nano-slice level
  • HitCounts - Fills histograms with number of hits, FEBs, and DCMs reporting as a function of UTC hour.
  • HitMaps - Fills histograms with hits reported as a function of detector coordinates.
  • TriggerPlots - Fills histograms with information about the number of triggers reported over time.
  • TQPlots - Fills histograms with charge reported per hit by each DCM as a function of time in the trigger window.
  • WLPlots - Fills the WatchList plots.

The goal of this organization is to allow for a single set of loops over the data to feed multiple histogram makers rather than forcing histogram makers to each re-implement this somewhat tricky set of nested loops. This should not only make the code cleaner, but more efficient.

Connecting histogram makers

To add new histograms, follow these steps:

1. Add the histograms you want to the file util/onmon-histos.csv. You can use your favorite spreadsheet editor, just make sure you save the file in the original .csv format (I had to learn that one the hard way.)

2. Next you need to make a new histogram producer. Decide what level of subscription your producer requires (see the Summary classes in the /producer directory for what information each summary contains.) For example, if you want to fill a histogram with cell number vs. time, then it will need to be a nano-slice summary subscriber. If you want to fill a histogram with byte-count vs. DCM number, then it will need to be a micro-slice summary subscriber. Make yourself a new producer class (easiest to do by copying an existing class such as HitCounts.cxx) and fill it with the necessary bits to make your new histograms.

3. Lastly, add your new histogram producer to the list of others contained in the OnMonProd.cxx constructor as:

  // Histogram fillers
  static NewHistoMaker  WhatEver;

Fire up the producer and watch your new histogram fill like magic!

(Here are Mark's original notes which, as usual, are more sophisticated than my simple words.)

Histogram makers need access to the Summary objects which contain the data they will want to plot. To get this access they sub-class the SummarySubscriber base class and set the bits required to get updates for the summaries they want. For example, a class HitCounts wanting to make and fill histograms of hit counts would be defined this way:

In HitCounts.h:

#include "OnlineMonitoring/producer/SummarySubscriber.h" 
namespace om {
  class HitCounts : public SummarySubscriber {
    void Get(const RawEventSummary& res);

In HitCounts.cxx:

#include "OnlineMonitoring/producer/HitCounts.h" 

// Guarantee one instance of this histogram-making class
static HitCounts hitCounts;

HitCounts::HitCounts() : SummarySubscriber(SummarySubscriber::kEvent)
{ }

The subscription is set in the constructor and can be OR'ed combinations of kEvent, kDataBlock, kMicroSlice, and kNanoSlice. For each subscription the subscriber must implement the appropriate Get@s:

Notice that the summaries from the higher-level event objects are made available to the lower-level event object; that is the @NanoSliceSummary
has access to the MicroSliceSummary, the DataBlockSummary, and the RawEventSummary. For example, the event header (trigger type, run, event numbers, date/time) information is contained in the RawEventSummary. Note, however, that some of the event-level information requires the entire event to be processed before its data is complete (for example, hit counts). The headers for the Sumamry objects mark which data can be relied upon by the lower level histogram makers and which will only be complete at the end of processing. For example, quoting from RawEventSummary.h

  // All subscribers can expect this data to be filled correctly
  unsigned int      fRun;        ///< Run number
  unsigned int      fSubrun;     ///< Subrun number
  unsigned int      fEvent;      ///< Event nunber
  unsigned int      fNdatablock; ///< Number of data blocks
  unsigned long int fT0;         ///< Trigger time in nova time units (64 Mhz ticks)
  float             fHour;       ///< A fractional hour of the day
  // Only event summary subscribers can expect this data to be correct
  unsigned int           fNhit;
  std::set<unsigned int> fDiblocks; ///< The list of diblocks in event
  std::set<unsigned int> fDCMs;     ///< The list of DCMs contributing to the event
  std::set<unsigned int> fFEBs;     ///< The list of FEBs contributing to the event

Producer Output

At the end of every subrun, the producer will write all of its histograms (the current histograms as well as all look-back histograms) to a root file labeled as onmon-subrun-[run#]-[subrun#].root in the directory /online_monitor/offline/onmon_temp_root_files/. A cronjob will wake up once per day and clean up old root files in this directory. The clean up script can be found on datamon here: /home/novadaq/bin/

Currently, any files less than 30 days old are left alone. Any "endsubrun" files that are older than 30 hours are deleted if they have a corresponding "endrun" file and moved to /online_monitor/offline/onmon_temp_root_files/saved/ otherwise. The idea here is that if a 30 day old "endsubrun" file exists without an "endrun" file, then that run didn't end well and the "endsubrun" files might contain information as to why. All "endrun" files older than 30 days are also moved to /online_monitor/offline/onmon_temp_root_files/saved/.