Introduction
Obtaining the
code
Running
the test program
Using the service
JobOptions
Reading the ntuple
|
|
Want to write out to a ROOT ntuple? Then ntupleWriterSvc is for
you! This Gaudi Service is designed to handle the ins and outs of
adding and updating an ntuple. User algorithms just provide a name
to identify the ntuple they desire to write to, the tag name for the
ntuple entry, and a value. ntupleWriterSvc does the rest!
ntupleWriterSvc is available from your neighborhood SLAC
cvs repository. You can find the most recent tagged version by checking
out this web page that lists the latest tags.
To become acquainted with the ntupleWriterSvc, try the
test application that is provided with the ntupleWriterSvc package.
Once ntupleWriterSvc has been set up using cmt, compile the test project
to generate the test application. Now check the jobOptions.txt file
in the src/test directory. You may need to update the following
entry, to point to a valid directory on your system:
// Output root ntuple file, specify by logical variable
NTupleSvc.Output = {"TESTALG DATAFILE='/NTUPLES/testAlg.root' OPT='NEW'"};
Now you are ready to run the test application. When it is complete,
there will be a new Root ntuple in the directory name you provided in the
NTupleSvc.Output job options entry. The ntuple will contain one
column called "MyFirstItem".
-
First, add "use ntupleWriterSvc" to the
requirements file for the application you wish to run.
-
Next setup the package, so that the settings are reset
to include ntupleWriterSvc
-
Update the jobOptions file:
-
Add ntupleWriterSvc to ApplicationMgr.ExtSvc
-
Add ntupleWriterSvc to ApplicationMgr.DLLs
-
Add ApplicationMgr.HistogramPersistency = "ROOT";
if it is not already in your jobOptions
-
Provide a list of ntuple names to the service, for
example: ntupleWriterSvc.tuple_name = { "ACD" };
-
Here we will create one ntuple, identified by
the tag "ACD".
-
Setup the output parameters for the NTupleSvc,
using the tag name(s) provided in your ntupleWriterSvc.tuple_name
list. Note that the NTupleSvc as well as ntupleWriterSvc can
accomodate multiple ntuples in one run. Here is an example
for settiing up the "ACD" ntuple:
NTupleSvc.Output = {"ACD DATAFILE='/NTUPLES/acdAlg.root' OPT='NEW'"};
-
Finally, for the algorithm you wish to use to
write to an ntuple, setup a new input parmeter to specify the
ntuple logical name. Here is an example for the acdReconAlg:
acdReconAlg.tuple_name = "ACD";
-
Next update your algorithm to use the ntupleWriterSvc
-
Add the include file: #include
"ntupleWriterSvc/INTupleWriterSvc.h"
-
Setup a member variable to access the
ntupleWriterSvc:
INTupleWriterSvc *ntupleWriteSvc;
-
Add a member variable to store the ntuple logical
name parameter that we just added to the job options file.
std::string m_tupleName;
-
In your algorithm's constructor, add a
declareProperty call for the logical name parameter:
declareProperty("tupleName", m_tupleName="");
-
In your algorithm's initialize routine, make sure
there is a call to "setProperties( )". This is a
call to the Gaudi routine that will extract your parameters from
the job options file.
-
In your algorithms's initialize routine, access
the ntupleWriterSvc:
// get a pointer to our ntupleWriterSvc
sc = service("ntupleWriterSvc", ntupleWriteSvc);
if( sc.isFailure() ) {
log << MSG::ERROR << "acdReconAlg failed to get the ntupleWriterSvc" << endreq;
return sc;
}
-
Lastly, during your algorithm's execute method,
call a routine to fill quantities in an ntuple. For example,
the acdReconAlg has a method called writeNTuple( ). This
routine, uses the ntupleWriterSvc to add items and their values to
a named ntuple. This example, adds 2 entries to the ntuple,
"ACD_TotEnergy" and "ACD_TileCount".
StatusCode acdReconAlg::writeNTuple() {
StatusCode sc = StatusCode::SUCCESS;
/// we must add our ntuples items to the ntuple here:
sc = ntupleWriteSvc->addItem(m_tupleName.c_str(), "ACD_TotEnergy", m_totEnergy);
sc = ntupleWriteSvc->addItem(m_tupleName.c_str(), "ACD_TileCount",
m_tileCount);
return sc;
}
-
NOTE: It is imperative that all items that
you expect to fill during the course of a run are setup via an
"addItem" call for the first and every event. An
ntuple will contain entries for all columns for every event.
We cannot add new columns during the course of a run.
So...if your addItem calls are dependent upon certain variables
being defined - provide alternate calls to addItem to fill in
dummy values for the columns in the ntuple. These dummy
values may be zero, or some outlandish value to flag this event as
one that does not have certain variables defined.
The only method users of ntupleWriterSvc need to be
concerned with is the addItem routine. The method is defined as
follows: StatusCode addItem(const char *tupleName, const char
*itemName, const float value); The first parameter is the
tag that identifies the ntuple that we wish to write to, such as
"ACD". The second parameter is the column name for the
item we wish to update, such as "ACD_TotEnergy", this will
be the name as it will appear in the Root ntuple. The third
parameter is a float, which contains the value to be stored in this
item for this event.
Reading the ntuple is actually fairly easy. The
ntuple only contains simple branches which contain a simple data
type..currently just doubles. So to read the ntuple in Root,
here is an example script: {
gROOT->Reset(); // roll back CINT context to last Save
// open the file
TFile *myTup = new TFile("I:/NTUPLES/testAlg.root");
TTree *myTree = (TTree*) myTup->Get("TESTALG/t1");
// open up a TBrowser
TBrowser tb;
// Draw a histogram of the MC X0,
// and apply cuts based on Y0 and Z0
myTree->Draw("MC_X0", "MC_Y0<10 && MC_Z0>40");
} To use this script for your particular root
file - you will have to modify 2 lines:
TFile *myTup = new TFile("I:/NTUPLES/testAlg.root");
TTree *myTree = (TTree*) myTup->Get("TESTALG/t1"); First
you need to open the correct root file in the TFile *myTup = new TFile(
) call.
Secondly, you need to access the correct name of the tree. Our
ntuple will be located within a directory named according to the
logical name we used in the job options file, this case "TESTALG".
Then the actual name of the tree will be "t1". If you
are in doubt about the name of the directory containing the TTree,
then open the TFile and the do "myTup->ls( )", that
should print the contents of the file.
|