Daniel Sigg, May 2001
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.
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 (" "));
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:
Get a working example from here. This example produces the following summary page.
Exercise: