New RootAnalysis - A Book Report

Heather and Matt have initiated a new iteration on our RootTreeAnalysis (RTA) macros. They have served us for some time and form the basis of the System Tests Root macros, but they are a tad awkward and in need of modernizing.

Original RTA Idea

The point was to make it easier to do easy things while accessing our Root trees and ntuples, such as opening files, rewinding them, event navigation; bulk histogram manipulation, such as clearing and writing out; and supplying standard locations to define user histograms and insert their analysis code.

 A single class was created that had member functions for these tasks.

 It got complicated and did not extend well, as we added more input files and differentiated analyses based on MC, Digi and Recon steps for the 3 subsystems. In addition, access to histogram pointers was awkward.

New Idea

 Matt proposed that we go with new(er) Root concepts of Selectors, Folders, Tasks and tree friends; and Heather has implemented it.

TSelector

A built-in function of TTrees that permits looping over the tree entries, with a well defined interface for initialization, event processing and termination.

TFolder

An organizational tool that allows one to segregate different kinds of objects and provides a mechanism for retrieving them. This is akin to Gaudi's TDS.

TTask

A configurable list of "algorithms" to run. Tasks can also have lists of sub-tasks. These would be the equivalent of Gaudi Algorithms.

Tree Friends

Allows one to associate other trees with one tree. One can then loop over the single tree and it makes sure all the others are read in lock-step too. If we had a naming convention for our trees and files, this would further simplify multi-tree access.

Implementation

Folders

Create folders for tasks, histograms and data pointers. eg for histograms:

void AcdDigiTask::CreateHistograms(TFolder *folder) {

    TH1F *PMT0001 = new TH1F("PMT0001", "PMT0001", 1000, 0, 1000);
    PMT0001->SetDirectory(0);
    folder->Add(PMT0001);

}

void AcdDigiTask::Exec(Option_t *option) {
    TH1F* pmt0001 = (TH1F*)gROOT->FindObjectAny("PMT0001");
    if (!pmt0001) {
        std::cout << "PMT0001 Histogram Not Found!" << std::endl;
        return;
    }

[though it looks to me like the fetch is depending on the histograms being in Root's "special" list of objects, not the histograms TFolder. Hmm. How does this work, since CreateHistograms provides no default value, but is called with no argument in DigiSelector::Begin. ?]

Selector

The selector needs to know what branches to read and what tasks to execute. Heather has set up an ACD Digi example, where tasks can register for the different types of Digi data and the selector will then only read those branches.

So far it requires hardwired knowledge of the branch structure and names, eg:

RequestedDigiData *rdd = (RequestedDigiData*)taskFolder->FindObjectAny("RequestedDigiData");
    if (rdd && rdd->AcdData()) {
        b_DigiEvent_acdDigiCol->GetEntry(entry);
        digiFolder->Add(m_acdDigiCol);
    } else {
        std::cout << "ACD not requested" << std::endl;
    }
    m_digiTask->ExecuteTask();



Another feature of the Selector is that only one Selector operates on a tree at a given time.
So, either we need some hierarchy of classes to handle MC, Digi and Recon or a single Selector with an overall list of tasks and a generic data registration scheme.

Tasks

The task's CreateHistograms function is called from the Selector's begin step. There does not seem to be an Init for Tasks, so maybe this is the best place.

User Side

Heather created a top-level macro that runs all this. It sets up paths and compiles everything. It defines the folders and tasks, opens the Digi file and executes the Selector.

Still to be done (IMHO)


R.Dubois Last Modified: 2004-05-09 19:32:07 -0700