|
In this tutorial we will go behind the job user interface and start to directly use the object data structure with the following:-
look_at_data_header()
{
..
}
void myAnaDataHeader(const MomNavigator* mom)
{
...
}
As it explains in the
summary
of the Macros page of the Companion's
First Steps: In C++ and ROOT
macros can be one of two sorts:-
gROOT->Reset();
JobC j;This gets us a JobC object with which we can create a JobCPath:-
j.Path.Create("Demo","");
You ought to be able to figure out what its doing from the
Configuring Jobs slide.
The path is empty, but the input module is effectively added at
the start so that running the path will read in records.If you are new to C++ the syntax may have you puzzled. The first part:-
j.Path.selects the public data member Path, which is a JobCPathModule object. The second part:-
.Create("Demo","");
requests that JobCPathModule creates a path called Demo.
Next we add another, special RootCommand module, selecting its Ana method:-
j.Path.Add("Demo","RootCommand::Ana");
and configure it so, when the Ana method is called, it in turn
calls our myAnaDataHeader function and passes it something called mom.
j.Path("Demo").Mod("RootCommand").Cmd("AddLine/Ana myAnaDataHeader(mom)");
mom is a MomNavigator. If you want to know more then you to look at
the MinosObjectMap slide.
For now though, all you need to know is, as always, Mom knows where
everything is!You might just be wondering how, when the RootCommand module runs, it knows where to find mom. This is a bit of ROOT magic, which registers the name of every object that gets created within its framework. When presented with an unknown name, it locates its address and type from this is the registry. If you don't like to rely on ROOT magic - which is wise if you plan to write plain C++ - you can mom from the JobC object:-
MinosObjectMap& mom = j.Mom;
Finally run the path 10 times
j.Path("Demo").RunNin(10);
RawRecord* raw = dynamic_cast<RawRecord*>(mom->GetFragment("RawRecord"));
Again, if you are new to C++ lines like this
may look a bit daunting. There are two things going on:-
mom->GetFragment("RawRecord");
Now if you look at
MomNavigator.h
you will see that GetFragment() is declared like this:-
TObject *GetFragment(const char *classname = 0,
const char *username = 0,
const char *streamname = 0 ) ) const;
it returns a TObject* not at RawRecord* which
inherits
from it.
RawRecord* raw = dynamic_cast<RawRecord*>(...);
does and then stores it in the variable raw. The dynamic_cast
operator is a recent addition to C++ and you will certainly come
across the older, C-style, casting which simply places the type
you want to convert to in parenthesis before the expression to
be converted. In this case it would be written:-
RawRecord* raw = (RawRecord*)mom->GetFragment("RawRecord");
which may be easier to read but is more dangerous which is why
that form is deprecated in item
DANG-12
of our
coding standards.
Converting a pointer to move up the inheritance tree is
always potentially dangerous. For example if the TObject
that mom returned was not embedded in a RawRecord what would happen?
Well the C-style cast would happily return a non-zero totally corrupt
pointer! At least dynamic_cast can do a check at run time and, if
the TObject isn't part of a RawRecord, return zero.
const RawHeader* head = raw->GetRawHeader(); cout << "Found a RawRecord header: " << endl; head->Print(); cout << endl;See MinosObjectMap for a warning if there is more than one RawRecord currently available.
It should produce 10 lots of output similar to this:-
Found a RawRecord header:
RawDaqSnarlHeader { Far| Data|2002-06-28 15:18:28.123984581Z}
Run 5963 SubRun 0 RunType 2 Snarl 2 TrigSrc 4 ErrorCode 0
loon -q $MINOS_TUTORIAL_MACROS/look_at_data_header.C $MINOS_TUTORIAL_DATA/F00018143_0000.mdaq.rootIt should produce 10 lots of output similar to this:-
Found a RawRecord header:
RawDaqHeader { Far| Data|2003-08-01 02:48:29.183670000Z}
Run 18143 SubRun 0 RunType 2 TimeFrame 0
Take
a look at the file
look_at_data_header.C
and try to understand it.Code like:-
RawRecord* raw = dynamic_cast<RawRecord*>(mom->GetFragment("RawRecord"));
const RawHeader* head = dynamic_cast<RawHeader*>(raw->GetRawHeader());
head->Print();
which follows from object to object via pointers has a very
serious flaw. What is it and how is it fixed?
RawRecord* raw = (RawRecord*)mom->GetFragment("RawRecord");
which is risky - it could have several. In our next example:
look_at_data_header_2.C
we do something a bit better:-
// Get an iterator over the fragments
TIter iter = mom->FragmentIter();
// Use TIter::Next() to get each TObject mom owns.
TObject* tobj = 0;
while ( tobj = iter.Next() ) {
// Convert TObject to a RecMinos.
RecMinos* rec = dynamic_cast<RecMinos*>(tobj);
if (rec) {
... process RecMinos objects
}
else {
... deal with everything else
}
}
so it loops over all of Mom's fragments and asks each it's type. In this case
we just see what RecMinos objects there are. These will include RawRecord
which inherit from RecMinos. If you want to be convinced of that then
one way would be to
browse the code.
Run it in the same way:-
loon -q $MINOS_TUTORIAL_MACROS/look_at_data_header_2.C $MINOS_TUTORIAL_DATA/F00018143_0000.mdaq.rootLooping over events printing out RawDataBlocks Our next macro: look_at_data_blocks.C goes beyond the printing of a of record headers to look at the data blocks held in a RawDataBlock which it does with:-
TIter itr = raw->GetRawBlockIter();
RawDataBlock* rawBlk = dynamic_cast<RawDataBlock*>(itr.Next());
while ( rawBlk ) {
cout << " " << rawBlk->GetName() << endl;;
rawBlk = dynamic_cast<RawDataBlock*>(itr.Next());
}
Run it:-
loon -q $MINOS_TUTORIAL_MACROS/look_at_data_blocks.C $MINOS_TUTORIAL_DATA/F00018143_0000.mdaq.rootLooping over events printing out hits from RawDigitDataBlock In our final macro look_at_data_hits.C we finally get to the hits from a RawDigitDataBlock. In order to do this we have to do 2 things:-
// Does the RawDataBlock inherits from or ir a RawDigitDataBlock
// (note: use this ROOT function because CINT's dynamic_cast
// doesn't return 0 when it should fail!)
if ( rawBlk->InheritsFrom("RawDigitDataBlock") ) {
RawDigitDataBlock* rddb = dynamic_cast<RawDigitDataBlock*>(rawBlk);
// .... See how many digitizations there are ...
Int_t numDigits = rddb->GetNumberOfDigits();
if ( numDigits > 10 ) numDigits = 10;
// ... and print out the first 10 at most.
for (unsigned idigit = 0; idigit < numDigits; ++idigit) {
const RawDigit* rd = rddb->At(idigit);
rd->Print();
}
loon -q $MINOS_TUTORIAL_MACROS/look_at_data_hits.C $MINOS_TUTORIAL_DATA/F00018143_0000.mdaq.root
| Contact: Nick West <n.west1@physics.ox.ac.uk> |
| Security, Privacy, Legal |
|