RIPE Database Search

By pressing the "Search" button you explicitly express your agreement with the RIPE Database Terms and Conditions.

Analyzing Test Box Data

Archived This content has been archived and is no longer actively maintained.
  1. Ask us for the data.
  2. Install ROOT on your system.
  3. Support files and examples.
  4. Advanced use
  5. Standalone ROOT based applications

1. Ask us for the data

This is easy. Simply send an email to tt-ops _at_ ripe _dot_ net and ask us for the data. We have tools to extract any subset from the full data-sample and can run them for you. A small subset can usually be extracted the same day, larger samples take longer.

For each day in the requested period, we will create a file containing all data originating from and recevied by your box.

the resulting set of files will be put on a special location of our FTP server that is only visible to you. Instructions on how to retrieve the data will be mailed to you. Since we do not have unlimited space on our server, please inform us when you have copied the files to your site.

At the RIPE NCC, we are using CERN's ROOT package to process and store all test traffic data. ROOT provides an "object oriented data analysis framework", featuring graphics, histogramming, a C++ interpreter and object I/O. This provides a nice environment for (interactive) analysis and data presentation. The files that we create are therefore using the ROOT file format, which brings us to the next question: how to get ROOT.

2. Install ROOT

ROOT is available for free and supported on a lot of platforms, including most Unices and Windows 95 or NT. Installation is described in the download section of the ROOT website, http://root.cern.ch. One can usually find a "new" or development version, a stable production version and "old" versions there. In general, go for the stable version. You have two options:

  • Download the complete ROOT source tree and install from scratch.
  • Download a precompiled binary distribution for your specific platform.

Note that in most installations you will have to set some environment variables prior to running the software (so ROOT knows where to look for its shared libraries). To verify your installation, it's a good idea to try to compile and run the suite of ROOT test programs found in the root/test directory. After that, proceed with a few of the tutorials from the ROOT website, in order to get a basic feeling for the program.

If you run into trouble, take a look at the ROOT website, in particular the HOWTO's as well as the archives of the RootTalk mailing list. If you have a problem, chances are that somebody has already seen and solved it before. The (draft) User's Guide gives a nice introduction as well as more background information on ROOT.

3. TTM support library and examples.

Once you have verified your ROOT installation to function properly, you are ready for the next step: creation of the support library for TTM analysis.

To allow easy combination of multiple files into one bigger data set, the test traffic data are stored in TTree objects. Each TTree has a collection (usually one day) of delay measurements, which are stored in objects of a class Delay, which has been defined by us. This class' definition and its member functions have to be made known to ROOT by dynamically loading a shared library.

The source code for the Delay class library can be loaded from our ftp site: ftp://ftp.ripe.net/test-traffic/ROOT/libDelay. Adapt the Makefile to suite your installation, then create the library by running make. Now you are ready for your first steps in TTM analysis:

  1. Start ROOT and load the delay library:
        $ root
    *******************************************
    * *
    * W E L C O M E to R O O T *
    * *
    * Version 2.25/03 14 September 2000 *
    * *
    * You are welcome to visit our Web site *
    * http://root.cern.ch *
    * *
    *******************************************

    CINT/ROOT C/C++ Interpreter version 5.14.50, Sep 2 2000
    Type ? for help. Commands must be C++ statements.
    Enclose multiple statements between { }.
    root [0] gSystem.Load("libDelay.so");
  2. attach a file with TTM data and load the TTree:
        root [1] TFile f("tt46.ripe.net.20000809.root")
    root [2] TTree *T = (TTree*)f.Get("tree");
    (in this case we load all data send from and received by box 46 on Aug 9th, 2000)

     

  3. create simple graphs, delay vs. time and delay distribution for packets send to tt43
    (example output here and here)
        root [3] T->Draw("PacketDelay", "TargetId==43");
    root [4] T->Draw("PacketDelay:ArrivalTime", "TargetId==43 && ArrivalTime != -1");

    Note: The "ArrivalTime != -1" condition restricts the data set to packets which did reach the target machine.

     

  4. inspect the data, look for events with delay >500ms
        root [5] T->Scan("PacketDelay:ArrivalTime:SourceId:TargetId", "PacketDelay>500");
    ************************************************************
    * Row * PacketDel * ArrivalTi * SourceId * TargetId *
    ************************************************************
    * 548 * 527.317 * 965779940 * 46 * 24 *
    * 1593 * 1098.764 * 965781130 * 46 * 39 *
    ...
    * 9051 * 572.667 * 965789844 * 46 * 24 *
    Type to continue or q to quit ==> q
    ************************************************************
    ==> 25 selected entries

  5. quit ROOT
        root [6] .q

In the examples above, the first string argument lists the parameter(s) to be plotted or printed, the second string argument provides a boundary condition that must be fulfilled. The parameters which are available for plotting/printing and selection are the data members of the Delay objects, as listed in the class definition file Delay.h.

4. Advanced use

loading more than one file


When more than one day's worth of data has to be analysed, the file loading procedure changes a bit. Instead of a TFile object, TTM data are now accessed via a TChain object:

        root [0] gSystem.Load("libDelay.so");
root [1] TChain T("tree");
root [2] T->Add("tt46.ripe.net.20000809.root")
root [3] T->Add("tt46.ripe.net.20000810.root")
root [4] T->Add("tt46.ripe.net.20000811.root")

The big advantage of ROOT is that apart from this initialization, the analysis code does not change; you can use TTree:Draw() and TTree:Scan() methods like above, ROOT's I/O system will take care of fetching the right data from the right file!

more control over display parameters

The default graphs produced by Draw() provide a quick insight in the data, but pretty soon you will find yourself in a situation where you want more control over the display, e.g. setting x- & y-axis scales, line & marker colors, and for comparison put two graphs on top of each other. For this purpose, one has to create a histogram object, which can be filled either by a call to the TTree Draw() method (or as we will see in a next example through individual calls to the histogram Fill() method while looping over the data):

  • Retrieve range for x-axis from the data:
        root [5] cout << T->GetEntries() << endl;
    214920

    root [6] T->Scan("ArrivalTime","","",1,0)
    ************************
    * Row * ArrivalTi *
    ************************
    * 0 * 965779328 *
    ************************

    root [7] T->Scan("ArrivalTime","","",1,214919)
    ************************
    * Row * ArrivalTi *
    ************************
    * 214919 * 966038395 *
    ************************
  • Create a TH2F histogram object and fill with TTree:Draw()
    (example output)
        root [8] TH2F h1("h1", "title", 200, 965779328, 966038395, 150, 0, 150.0) 
    root [9] T->Draw("PacketDelay:ArrivalTime>>h1","TargetId==23");
  • Set color attribute, switch to human friendly time and redraw:
    (example output)
        root [10] h1->SetMarkerColor(2);
    root [11] h1->GetXaxis()->SetTimeDisplay(1);
    root [12] h1->GetXaxis()->SetTimeFormat("%H:%M");
    root [13] h1->Draw();
  • Create second histogram, store data for another target and overlay with first histogram:
    (example output)
        root [14] TH2F h2("h2", "title", 200, 965779328, 966038395, 150, 0, 150.0)
    root [15] T->Draw("PacketDelay:ArrivalTime>>h2","TargetId==30")
    root [16] h2->SetMarkerColor(4);
    root [17] h1->Draw(); /* redraw h1 */
    root [18] h2->Draw("SAME"); /* overlay h2 */

looping over all data

When the data selection is more complicated than a simple if clause, when more than one histograms should be filled in a single pass through the data or when the analysis requires access to individual delay measurements, one has to write some code that loops over all data. For non time-critical applications this can be in the form of a macro for ROOT's C++ interpreter. For example, if the file macro.C contains the following code:

    {
TChain T("tree");
T.Add("tt46.ripe.net.20000809.root");
T.Add("tt46.ripe.net.20000810.root");
T.Add("tt46.ripe.net.20000811.root");

TH2F *hist1, *hist2;
hist1 = new TH2F("h1", "delays to tt01", 200, 965779328, 966038395, 150, 0, 150);
hist2 = new TH2F("h2", "delays to tt31", 200, 965779328, 966038395, 150, 0, 150);

// create a Delay object for storage of per event data
Delay *delay = new Delay();
T.SetBranchAddress("delay", &delay);

Int_t nTotalEvents = T.GetEntries();
cout << "Total #entries:" << nTotalEvents << endl;

for (Int_t eventNo=0; eventNo < nTotalEvents; eventNo++) {

// read next delay into memory and check clock status
if ( (T.GetEvent(eventNo) > 0) && (delay->ClocksOK()) ) {

// we do have some data AND both source and target clocks
// have good status

// get parameters
Double_t packetDelay = delay->GetPacketDelay();
Double_t arrivalTime = delay->GetArrivalTime();

Int_t targetId = delay->GetTargetId();

if (targetId == 1) {
hist1->Fill(arrivalTime, packetDelay);
}
else if (targetId == 31) {
hist2->Fill(arrivalTime, packetDelay);
}
}
}

hist1->Draw();
hist2->SetMarkerColor(2);
hist2->Draw("SAME");
}

it can be executed in ROOT by typing:
(example output)

    root [17] .x macro.C

The above is sufficient for simple macros, but when code becomes more complex and the user wants to pass parameters to the macro, the loading procedure changes a little. First modify the source file such that instead of a unnamed {...} block it has (one or more) named functions, e.g. create a file macro2.C containing:

    void mymacro(char *box="tt01.ripe.net", Int_t target=2){
cout << "Boxname: " << box << endl;
cout << "TargetId: " << target << endl;
}

then load the file with

    root [18] .L macro2.C

Now the "mymacro" function can be executed as often as desired:

    root [19] mymacro();      /* use default parameters */
Boxname: tt46.ripe.net
TargetId: 2

root [20] mymacro("tt46.ripe.net",51);
Boxname: tt46.ripe.net
TargetId: 51

Since the macros are really C++ code, they provide a powerfull means of scripting: systems calls, library functions, ROOT classes and private class definitions, all are available for coding macros. However, when processing a lot of data, the overhead of interpretted C++ becomes noticable and will slow analysis; at that point one has to switch from the interactive environment, to a more batch oriented mode, where the user's code is compiled and linked with ROOT libraries to make an executable. This is discussed in the next section.

5. Standalone ROOT based applications

In the preceding sections, we showed examples of looking at TTM data from within ROOT's interactive environment. Here we discuss how to make applications which build on the ROOT framework, but do not use the C++ interpreter. This is especially usefull when the application should run in batch mode without human intervention, or when you reach limitations of the interpreter.

After presenting the concepts, we will continue with the case study of the moderately complex delayplots program we use internally to create daily TTM plots.

Turning a macro into a program

When a program is not running in the ROOT CINT environment, the code has to be extended with appropriate class definitions (i.e. #include statements) and intialisation of the ROOT framework. In general each ROOT class has a corresponding include file (e.g. TTree.h for TTree objects), but when in doubt one can search for the correct file in the root/include directory.

If we take the above unnamed macro as example, the following needs to be changed to make it ready for standalone usage:

  1. load the class definitions:
        #ifndef __CINT__

    #include "TROOT.h"
    #include "TApplication.h"
    #include "TCanvas.h"
    #include "TChain.h"
    #include "TTree.h"
    #include "TH1.h"
    #include "TH2.h"

    #include "Delay.h"

    #endif
    The last file has the definitions of the TTM Delay class, the others are from ROOT itself. Enclosing the statements in a #ifndef CINT clause, allows the same code to be called either as a macro or compiled as standalone program.

     

  2. put the {..} block in a function:
        main () {
    ...
    }
  3. add code for ROOT initialisation
        #ifndef __CINT__
    TROOT simple ("TTM", "Plots");
    TApplication app("delayPlots", NULL, NULL, NULL, 0);
    #endif
  4. create a canvas for graphics output, before calling the histogram Draw() methods.
    	TCanvas canvas();	/* Default sized canvas */
  5. after drawing histograms, update canvas and enter the ROOT event loop to show window content and allow user interaction.
            canvas.Update();
    #ifndef __CINT__
    app.Run();
    #endif

Now you can compile the code, using compiler options similar to those in the Makefile from the ROOT test suite (root/test/Makefile).

 

The delayplots program

As an example of a moderately complex standalone ROOT application, we publish the source of the delayplots program (which we use at RIPE NCC to create the daily TTM plots) on our FTP site. It illustrates some advanced concepts of ROOT, such as subdividing the Canvas to get four graphs on one page, color attributes, graphics output to PostScript file etc. The bulk of the work is carried out by the DelayPlots class, specifically through the public methods Fill(), which processes all requested data and fills the histograms), and Plot(), which creates plots in PostScript and, if requested, GIF format.

Disclaimer: the code is published as an example, to help you build your own ROOT application program. By no means can we guarantee this is the latest version of the code; also it may not work in your environment without modification (because of dependencies on RIPE NCC's internal TTM configuration database).