Fermilab


MINOS Offline Documentation
[home] [installing MINOS software] [supported platforms] [package links] [mailing list] [HyperNews] [FAQ] [computing help] [MINOS glossary] [archives]

HowTo: make ROOT and JobControl play nice



(note: configuring offline jobs via .jcm language is depreciated)

Rationale

I was part of the original group that recommended MINOS use ROOT as the basis for our framework ( Software_Planning_Report.html). One of the aspects of ROOT that I found compelling was the ability to use the CINT (C++ interpreter) to bypass some of the compile-link-run cycle during code development. To that end I've retained an interest in keeping alive the ability to write and use "C++ macros" in the framework.

On the one hand Mark Messier has developed a nice job control system for assembling a job from component pieces and configuring and running those paths via jcm scripts. The problem is that it is very batch-oriented: the components had to be precompiled JobCModules and there was no way to "talk" to root except by writing C++ and compiling it into a module or something a module would call from one of the shared libaries.

Talking to bare ROOT

Some times during the processing of a .jcm script one wants to interact with root. Perhaps it's to load a library, or run a C++ macro. This is now handled by the JobCRootModule. This module is automatically included in a hidden path in the same way that JobCMsgModule is. Users should not attempt to explicitly load another copy. The commands expected to be used most commonly are described below. These would be inserted into the users .jcm script at the appropriate points.

Available commands

Running and (pseudo-)compiling macros during .jcm processing

/Root/RunMacro <macro.C> // root [] .x <macro.C> /Root/LoadMacro <macro.C> // root [] .L <macro.C> /Root/CompileMacro <macro.C> // root [] .L <macro.C>++ Run or Load a macro file, like .x or .L at ROOT prompt

Arbitrary ROOT command processing

/Root/ProcessLine <arbitrary text> Process line just like at ROOT prompt

Loading dynamic libraries

/Root/LoadLibrary <libraryName> Make a dynamic library available (via gSystem) /Root/LoadClass <className> <libraryName> Make a class available out of a dynamic library (via gROOT)

Configuring where ROOT looks for macros

/Root/MacroPath/Add <location(s)> /Root/MacroPath/Reset [<full list>] /Root/MacroPath/Show Manipulate the locations where ROOT looks for macros; path is a colon separated list: Add to the front of the list Reset to fixed value (default: initial ROOT defined value) Show the current setting

Using the ROOT object statistics facility

/Root/ObjectStat/Set [1|0] /Root/ObjectStat/Print TObject statistics collection (via gObjectTable): Turn [on|off] the statistics collection (default: on) Print the gObjectTable

Miscellaneous ROOT commands

/Root/Reset Reset ROOT /Root/SaveContext Have the interpreter save the current context /Root/SetStyle <styleName> Set the ROOT Style

Example .jcm

#======================================================================= # # A simple .jcm demonstrating the JobCRootModule facilities # # usage: demojob -bqx test_root.jcm # # rhatcher@fnal.gov #======================================================================= echo help Root # reset ROOT /Root/Reset # set the ROOT "style" to "Default" /Root/SetStyle Default # load some dynamic libraries /Root/LoadLibrary libRecoBase.so /Root/LoadClass MSTClusterListModule libBubbleSpeak.so # enable TObject statistics accumulation (poor mans leak checking) /Root/ObjectStat/Set 1 # run a "unnamed" macro /Root/RunMacro root_unnamed.C # run a macro that has a function with the same name as the file # and takes a single int argument /Root/RunMacro root_named.C(999) # load a macro that defines, amongst others, the functions # FillIntArray(Int_t* array, Int_t n) # DumpIntArray(Int_t* array, Int_t n) # this pseudo compiles it making it available for simple calling /Root/LoadMacro FileContains_DumpIntArray.C # compile, using the system compiler a file, producing and linking # in the resulting dynamic library /Root/CompileMacro good_code.cxx # process some arbitrary lines just like typing at the ROOT prompt /Root/ProcessLine Int_t n = 100 /Root/ProcessLine cout << n << endl /Root/ProcessLine Int_t *myarray = new Int_t[n] /Root/ProcessLine FillIntArray(myarray,n) /Root/ProcessLine DumpIntArray(myarray,n) /Root/ProcessLine #include "TString.h" /Root/ProcessLine TCanvas *cv1 = new TCanvas("cv1","cv1",600,600); # show the the TObject statistics, turn off accounting /Root/ObjectStat/Print /Root/ObjectStat/Set 1

Talking to ROOT during JobControl path processing

The JobCRootCommandModule provides a way to call scripts (or individual root commands) at various points in the job path processing (as opposed to the processing of the .jcm itself described above).

Let's take the example of having a C++ macro script one wanted run during the BeginJob phase, call this noargs.C. And there is another to be run at a particular point while running a path: rummage_mom.C. If one defines a job path in rootcmd.jcm one can run the path using demojob -bqx rootcmd.jcm.

rootcmd.jcm

#======================================================================= # # A simple .jcm demonstrating the JobCRootCommandModule facilities # # usage: demojob -bqx rootcmd.jcm # # rhatcher@fnal.gov #======================================================================= # load the macros so they aren't re-pseudo-compiled each time /Root/LoadMacro noargs.C /Root/LoadMacro rummage_mom.C # create a path /Path/Create RootCmdTest \ Input::Get \ RerootToRawDataModule::Get \ RootCommand::Ana # add a line that is processed at BeginJob -- no mom available so # macro better not rely on there being one /RootCmdTest/RootCommand/AddLine/BeginJob noargs() # add a line that is proccessed each time RootCommand::Ana is # add a line that is proccessed each time RootCommand::Ana is # encountered in the RootCmdTest path /RootCmdTest/RootCommand/AddLine/Ana rummage_mom(mom,"Ana") /RootCmdTest/Input/Add root_files/gm_far_cosmic_2_hapr01.root /RootCmdTest/Run Nin 5

The output

RootCmdTest(0 in 0 out 0 filt.) 1) Input::Get in=0 pass=0 fail=0 t= 0.00 s 2) RerootToRawDataModule::Get in=0 pass=0 fail=0 t= 0.00 s 3) RootCommand::Ana in=0 pass=0 fail=0 t= 0.00 s | nevts = 8327 ngeos = 1 MINFast::GetEvent: New REROOT_Event record 0 comes from REROOT_Geom record 0 ******** this is a macro with no args ::AddToCrate cutting all raw values < 0.299900 rummage_mom got mom = 0x93d4580 Ana List of Fragments in MomNavigator: [0] RawRecord: "" rummage_mom got mom = 0x93d4580 Ana List of Fragments in MomNavigator: [0] RawRecord: "" Processed 2 records: RootCmdTest(2 in 2 out 0 filt.) 1) Input::Get in=2 pass=2 fail=0 t= 0.08 s 2) RerootToRawDataModule::Get in=2 pass=2 fail=0 t= 0.14 s 3) RootCommand::Ana in=2 pass=2 fail=0 t= 0.36 s

noargs.C macro (run at BeginJob)

void noargs() { cout << " ******** this is a macro with no args" << endl; }

rummage_mom.C macro (run at RootCommand::Ana)

void rummage_mom(const MomNavigator* mom, char* byWhom) { cout << "rummage_mom got mom = " << mom << " " << byWhom << endl; if (!mom) { cout << "rummage_mom had a null mom ... attempt JobCROOT::GetMom()"; // Attach the current mom ... may fail with an assert() JobCROOT& jc = JobCROOT::Instance(); MomNavigator *mom = jc.GetMom(); } // yes, this duplicates the functionality of DemoEventDump::DumpFragments // but it is meant only to be *instructive*, presumably one wants // to do more with what is in "mom" than simply dump it TIter fitr = mom->FragmentIter(); cout << "List of Fragments in MomNavigator:" << endl; TObject* tobj; int i = 0; while (tobj = (fitr()) ) { cout << " [" << i << "] " << tobj->ClassName() << ":" << tobj->GetName() << " \"" << tobj->GetTitle() << "\"" << endl; } }


Last Modified: $Date: 2002/08/13 17:46:21 $
Contact: rhatcher@slac.stanford.edu
Page viewed from http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/howto_rootmodule.html
Fermilab
Security, Privacy, Legal Fermi National Accelerator Laboratory