DMT: Html API
Quick Start Guide

Daniel Sigg, May 2001


  1. Overview
  2. What do I have to do
  3. Example


Overview

A monitor must present summary information of its state and of its current results on a web page which can be accessible from the monitor observer page. The DMT libraries contain a set of html classes which make generating the html text straight forward. The summary page may contain live performance quantities such as statistical measures or may contain a list of the last few triggers.



What do I have to do

Here is a code fragment which computes a set of statistical values and writes them to a web page once a minute:

#include <math.h>
#include <string>
#include <iostream>
#include <fstream>
#include "TSeries.hh"
#include "DatEnv.hh"
#include "Time.hh"
#include "html/writer.hh" // Include Html API(s)
#include "html/Attrib.hh"
#include "html/align.hh"
#include "html/color.hh"
#include "html/document.hh"
#include "html/font.hh"
#include "html/hline.hh"
#include "html/image.hh"
#include "html/label.hh"
#include "html/link.hh"
#include "html/size.hh"
#include "html/style.hh"
#include "html/table.hh"
#include "html/text.hh"

// Html Text
const char* const kHtmlTitle = "My Monitor";
const char* const kHtmlAuthor = "Me";
const char* const kHtmlDescription =
   "My monitor computes my values...";
const char* const kHtmlLIGO =
   "Laser Interferometer Gravitational-wave Observatory ";
const char* const kHtmlLIGOLink = "http://www.ligo.caltech.edu";
const char* const kHtmlFilename = "summary.html";

class MyMonitor : public DatEnv {
   public:
      MyMonitor (int argc, const char* argv[]);
      virtual ~MyMonitor() {}
      virtual void ProcessData();
      virtual void Reset();
      virtual void Summary (const Time& t);  // Write summary info
   private:
      TSeries*     fData[3];   // Input data
      double       fY[3][8];   // Sum, Sum square, N, values
   ...
   };

EXECDAT (MyMonitor);   // DMT Framework

// Constructs the monitor and subscribes the data objects
MyMonitor::MyMonitor (int argc, const char* argv[])
: DatEnv (argc, argv) {
   Reset();
   fData[0] = fData[1] = fData[2] = 0;
   getDacc().addChannel ("H0:PEM-MX_SEISX", 1, fData+0);
   getDacc().addChannel ("H0:PEM-MX_SEISY", 1, fData+1);
   getDacc().addChannel ("H0:PEM-MX_SEISZ", 1, fData+2);
   ...
}
// Get some data and compute the statistics
void MyMonitor::ProcessData() {
   // Calculate the statistical values
   for (int i = 0; i < 3; ++i) {
      fY[i][0] += fData[i]->getNSample();
      fY[i][1] += fData[i]->getNSample()*fData[i]->getAverage();
      fY[i][2] += (*fData[i]) * (*fData[i]);
      if (fY[i][0] > 1) {
         fY[i][3] = fY[i][1] / fY[i][0];
         fY[i][4] = sqrt ((fY[i][2] - fY[i][1]*fY[i][1]/fY[i][0]) /
                    (fY[i][0] - 1.));
      }
   }
   // Write values every 60 sec
   if (fData[0]->getStartTime().getS() % 60 == 59) {
      Summary(fData[0]->getStartTime().getS()-59);
      Reset();
   }
   ...
}
// Reset statistics
void MyMonitor::Reset() {
   for (int i = 0; i < 3; ++i) {
      for (int j = 0; j < 8; ++j) {
         fY[i][j] = 0;
      }
   }
}
// Write summary information to web page
void MyMonitor::Summary (const Time& t) {
   // Html document
   html::document doc (kHtmlTitle);
   // Title
   html::block titleblk ("center");
   titleblk.lineBreak();
   html::text title (kHtmlTitle);
   html::font fonttitle ("Helvetica");
   title.setFont (fonttitle);
   title.setColor (html::color (0, 0, 128));
   title.setSize (html::size (+4));
   titleblk.addObject (title);
   titleblk.lineBreak();
   titleblk.addObject (html::text ("&nbsp;"));
   doc.addObject (titleblk);
   doc.addObject (html::hline());
   // Short description
   doc.addObject (html::text (kHtmlDescription));
   doc.addObject (html::hline());
   // Result table
   html::table results;
   results.addColumn ("Channel name");
   results.addColumn ("Mean");
   results.addColumn ("Sigma");
   results.addColumn ("Skewness");
   results.addColumn ("Kurtosis");
   results.addColumn ("Outliers");
   for (int i = 0; i < 3; ++i) results.addRow();
   for (int i = 0; i < 3; ++i) {
      results.insertData (i, 0, html::text (fData[i]->getName()));
      results.refCell (i, 0).setAlign ("left");
      for (int j = 0; j < 5; ++j) {
         results.insertData (i, j+1, html::text (fY[i][j+3]));
         results.refCell (i, j+1).setAlign ("right");
      }
   }
   doc.addObject (results);
   doc.addObject (html::hline());
   // Last update time
   html::block updateblk ("center");
   html::text lasttime ("This page was last updated: ");
   char buf[128];
   lasttime << TimeStr (t, buf, "%M %d, %Y at %H:%N:%S");
   updateblk.addObject (lasttime);
   updateblk.lineBreak();
   // Author
   html::text author ("This monitor was written by ");
   author << kHtmlAuthor;
   updateblk.addObject (author);
   doc.addObject (updateblk);
   doc.addObject (html::hline());
   // Logo
   html::block logoblk ("div");
   logoblk.addAttr ("align", html::align ("right"));
   logoblk.addObject (html::link (kHtmlLIGO, kHtmlLIGOLink));
   html::image logo;
   logo.setSource ("ligo_logo.gif");
   logo.setWidth ("80");
   logoblk.addObject (logo);
   doc.addObject (logoblk);
   // Write web page to file
   ofstream out (kHtmlFilename);
   if (out) {
      html::writer htmlout (out);
      doc.write (htmlout);
   }
}


From the code fragment above we can see that the following steps are necessary to add support for html output:

  • Include the Html API.
  • Compute the summary information.
  • Write the information to a web page on a regular basis.

  • All monitors should implement summary information and make it available through a web page.



    Example

    Get a working example from here. This example produces the following summary page.

    Exercise:

  • Add the skewness and the kurtosis to the statistical values.
  • Make the statistics robust by throwing out all data points beyond 5 sigma; add the number of outliers to the result page.
  • Modify the above example to include an arbitrary number of channels.

  •