SLAC PEP-II
BABAR
SLAC<->RAL
Babar logo
HEPIC E,S & H Databases PDG HEP preprints
Organization Detector Computing Physics Documentation
Personnel Glossary Sitemap Search Hypernews
Workbook Home Introduction Account Setup QuickTour Packages Modules Unwrap page!
Event Information Tcl Commands Editing Compile and Link Run the Job Debugging
Check this page with the
W3C Validator
(More checks...)
Parameters Tcl Files Find Data Batch Analysis ROOT Tutorial

Run-time parameters

One of the major advantages of BaBar's Framework/module code structure is that it gives the user run-time control of an analysis job. The user can enable or disable a module in the execution path, or use the module talk command to change a module's run-time parameters while running the analysis. All of these changes can be implemented without having to recompile or relink the code.

In the Framework section, you learned how to talk to modules and reset their run-time parameters. But you found that the Workbook's example module, QExample, does not yet have any run-time parameters. In this section, you will upgrade some of QExample's parameters to run-time parameters.

The AbsParm family

BaBar's C++ class for run-time parameters is called AbsParm. There are many different types of AbsParm, including:
   AbsParmDouble
   AbsParmGeneral<T>
   AbsParmFilename
   AbsParmString
   AbsParmBool
   AbsParmIfdStrKey
   AbsParmVector<T>
   AbsParmNamedObject<T> 
   AbsParmNamedValue<T>
   AbsParmPairs 
In particular, two important AbsParmGeneral<T> types are:
AbsParmGeneral<double>
AbsParmGeneral<int>
the AbsParm classes for double and integer run-time parameters.

Note that some of the header files for members of the AbsParm family are stored the Framework package, while others are stored in the the AbsParm package. When you #include your AbsParm header file, make sure you get the package right!

Creating run-time parameters

To turn a parameter into a run-time parameter, the first step is to declare it as an AbsParm of the same type. For example, suppose you want to define a maximum lepton momentum, _pMaxLep, as a run-time parameter. In the module's header file, #include the AbsParm header file:

#include "Framework/AbsParmGeneral.hh"
and declare the parameter:
private:

AbsParmGeneral<double> _pMaxLep;
The next step is to initialize the parameter. The place to do this is in the module's constructor (in the module's .cc file):
MyModule::MyModule( const char* const name,
                  const char* const description )
  : AppModule( name, description ),
    _pMaxLep("plmax", this, 1.5)
{

Note the syntax: the initialization goes after "AppModule( name, description)," and before the first curly bracket "{". When you declare/initialize an AbsParm, it is passed three arguments.

AbsParm parameters make sense only in the context of module classes. The command name ("plmax") is the name used from the Framework (when talking to the module) to access the parameter. The value (1.5) is the (default) value of the run-time parameter. This value is what the user can change from within the Framework.

Declaring a module data member of an AbsParm type is not enough to make it accessible to/from the Framework. It needs to be a member of the module's commands list. This is accomplished by the following append command:

   commands()->append(& name);
This command also goes in the module's constructor, but it is placed after the curly bracket:
MyModule::MyModule( const char* const name,
                  const char* const description )
  : AppModule( name, description ),
    _pMaxLep("plmax", this, 1.5)
{
  commands->append( & _pMaxLep);
}

Now _pMaxLep is a run-time parameter. To use it in your code (ie, in the event or beginJob functions), you use one of AbsParm's public member functions:

For example, to use _pMaxLep in your code:
MyModule::event(AbsEvent* anEvent) {
...
if (pLepton > _pMaxLep.value() )  nFast++;
This has the same effect as:
if (pLepton > 1.5 )  nFast++;
But now _pMaxLep is a run-time parameter. So if it is reset to 2.0 in a mod talk session,
> mod talk MyModule
MyModule> plmax set 2.0
then the effective statement becomes:
if (pLepton > 2.0 )  nFast++;

Example 4: Run-time parameters example

(It's Example 4 because the last example in the Editing Code section was Example 3.)

Now let's put this together and modify the QExample module to take advantage of the Framework's interactive capabilities. This example assumes that you have followed the instructions in Example 2 of the Workbook's editing code section, and modified QExample to include a momentum histogram. If not, then you can copy the modified QExample module from:

$BFROOT/www/doc/workboook/examples/ex2/

This time, instead of modifying QExample, you will create a new module based on QExample. To begin, copy your QExample.cc and .hh files into ones named ParmExample.cc and .hh respectively. You will need to uniformly change all instances of QExample to ParmExample.

In the ParmExample header file add the following private data members to the class definition/declaration:

AbsParmGeneral<int>    _nbins;
AbsParmGeneral<double> _pMin;
AbsParmGeneral<double> _pMax;
AbsParmIfdStrKey _trackList;

The first three AbsParm variables will be used for the momentum histogram parameters (number of bins, and the x-axis low and high limits).

The fourth AbsParm variable will be used for the name of the BtaCandidate list (for example, "ChargedTracks"). At first glance this looks like a string, so you might think that this should be an AbsParmString. But in fact, BtaCandidate list names are not strings. Their class is "IfdStrKey". So the correct AbsParm type is AbsParmIfdStrKey.

To use these new data type you will need to #include the appropriate header files in ParmExample.hh:

#include "Framework/AbsParmGeneral.hh"
#include "AbsParm/AbsParmIfdStrKey.hh"

(As mentioned above, for some reason, some AbsParm header files are stored in Framework, and some in AbsParm.)

Now, in the .cc file, initialize the variables in the constructor declaration (before "{"), and add the parameters to the command list in the constructor (after "{"):

ParmExample::ParmExample( const char* const name,
                  const char* const description )
  : AppModule( name, description ),
    _nbins("nbins",this,25),
    _pMin("pMin",this, 0.),
    _pMax("pMax",this, 1.0),
    _trackList("trackList", this, "ChargedTracks")
{
  commands()->append( & _nbins );
  commands()->append( & _pMin );
  commands()->append( & _pMax );
  commands()->append( & _trackList );
}

In this example the command names are the same (aside from the "_") as the AbsParm names, but that is not required.

The commas can be tricky, so be careful: Notice that all the parameter initializations have commas after them, except the last one. AppModule( name, description ) also gets a comma (unless there are no run-time parameters, making it the last item on the list).

The final step is to use these parameters in the context of the module code. When you booked the momentum histogram you explicitly passed values for the number of bins, low- and high-range values. Now you want the code for your histogram to use these interactive parameters. Recall each AbsParm type of parameter has an accessor function named value(). Use this function to pass the histogram manager each parameter's value.

   
_pHisto = manager->histogram("pTrack", _nbins.value() , _pMin.value(), _pMax.value() );

Now changes to these parameter values will be reflected in changes to the different aspects of the histogram.

You may have noticed that I changed the name of the histogram from "Momentum" to "pTrack." I did this so that it would not overwrite QExample's Momentum histogram. For the same reason, let's change the name of the number-of-tracks histogram as well:

 _numTrkHisto = manager->histogram("nTrack",  20, 0., 20. ); 

(You could choose to make _numTrkHisto's settings into run-time parameters as well, but we will not do that in this example.)

Similarly, you can replace the explicit call to "ChargedTracks" with the run-time parameter as follows:

  HepAList<BtaCandidate>* trkList  =
    Ifd<HepAList< BtaCandidate > >::get(anEvent, _trackList.value());

After making these changes you will need to add ParmExample to the Framework by modifying the AppUserBuildBase.cc file. Instead of replacing QExample, let's append ParmExample to the same path. That way you can compare the two modules from within the Framework. Add the following lines to AppUserBuildBase.cc, just after the equivalent lines for QExample:

#include "BetaMiniUser/ParmExample.hh"
and
  theBuild->add(new ParmExample("ParmExample", "Run-time parameter example module"));

The last step is to modify MyMiniAnalysis.tcl to add your new module to the path. Again after the equivalent line for QExample, put:

path append Everything ParmExample

A working example of the ParmExample module (and the associated AppUserBuildBase.cc and MyMiniAnalysis.tcl files) is provided in:

$BFROOT/www/doc/workboook/examples/ex4/

Because you changed C++ code (.cc and .hh files), you will have to recompile and relink for your new module to be added to the framework:

ana31> gmake clean
ana31> rm all.log
ana31> bsub -q bldrecoq -o all.log gmake all

For more information about compiling and linking, refer back to the Compile and Link section.

Run the executable and investigate the two modules by looking at the module talk options. Then analyse a few events, change some parameters, and analyse further events. Here is a sample dialog of such an investigation:

ParmExample investigation


ana31/workdir> BetaMiniApp snippet.tcl

         (Lots and lots of output...)

> echo The echo command prints whatever I say.

The echo command prints whatever I say.

> mod talk QExample

QExample> help

Command(s) available in the "QExample" module:

      echo              Send text argument to stdout (useful in scripts).
      exit              Leave the current menu, module, or process
      help              Bring up help text for the current context.
      show              Display the value of any parameters or statistics.
      sourceFoundFile   Source file in $BFDEFAULTSEARCHPATH or $BFSEARCHPATH.
      verbose           bool parameter: set or list.
      production        bool parameter: set or list.
      enableFrames      bool parameter: set or list.

QExample> echo Nothing interesting to do in QExample.  I'm getting out of here.

Nothing interesting to do in QExample.  I'm getting out of here.

QExample> exit

> mod talk ParmExample

ParmExample> show

Current value of item(s) in the "ParmExample" module:

      Value of verbose for module ParmExample: f
      Value of production for module ParmExample: f
      Value of enableFrames for module ParmExample: f
      Value of nbins for module ParmExample is 50
      Value of pMax for module ParmExample is 2
      Value of pMin for module ParmExample is 0
      Value of trackList for module ParmExample: IfdStrKey(ChargedTracks)

ParmExample> echo Look - there are the new parameters I created!

Look - there are the new parameters I created!

ParmExample> echo I wonder if I can change their values.

I wonder if I can change their values.

ParmExample> help

Command(s) available in the "ParmExample" module:

      echo              Send text argument to stdout (useful in scripts).
      exit              Leave the current menu, module, or process
      help              Bring up help text for the current context.
      show              Display the value of any parameters or statistics.
      sourceFoundFile   Source file in $BFDEFAULTSEARCHPATH or $BFSEARCHPATH.
      verbose           bool parameter: set or list.
      production        bool parameter: set or list.
      enableFrames      bool parameter: set or list.
      nbins             general parameter: set or list.
      pMax              general parameter: set or list.
      pMin              general parameter: set or list.
      trackList         string key parameter: set or list.

ParmExample> pMin set -1.5

ParmExample> pMax set 1.5

ParmExample> nbins set 100

ParmExample> trackList set GoodTracksLoose

ParmExample> show

Current value of item(s) in the "ParmExample" module:

      Value of verbose for module ParmExample: f
      Value of production for module ParmExample: f
      Value of enableFrames for module ParmExample: f
      Value of nbins for module ParmExample is 100
      Value of pMax for module ParmExample is 1.5
      Value of pMin for module ParmExample is -1.5
      Value of trackList for module ParmExample: IfdStrKey(GoodTracksLoose)

ParmExample> echo Parameters successfully changed.

Parameters successfully changed.

ParmExample> exit

> mod talk KanEventInput

KanEventInput> input add /store/SP/R14/001237/200309/14.3.1c/SP_001237_000533

KanEventInput> input list 

Files:
       /store/SP/R14/001237/200309/14.3.1c/SP_001237_000533
Components:
            hdr
            tag
            aod
            cnd


KanEventInput> exit

> echo Okay,  I guess I've done enough.  Now run the job.

Okay,  I guess I've done enough.  Now run the job.

> ev beg -nev 40

       (Lots and lots of output...)

> exit

> ana31/workdir>

Now take a look at your new histogram in ROOT:

ana31/workdir> bbrroot

root[] TFile f("myHistogram.root");

root[] f.ls();
TFile**         myHistogram.root        Created for you by RooTupleManager
 TFile*         myHistogram.root        Created for you by RooTupleManager
  KEY: TH1F     h1d1;1  MC reco abs mtm difference
  KEY: TH1F     h1d2;1  Reco track momentum
  KEY: TH1F     h1d3;1  Tracks per Event
  KEY: TH1F     h1d4;1  Momentum
  KEY: TH1F     h1d5;1  nTrack
  KEY: TH1F     h1d6;1  pTrack
  KEY: TH1F     h1d7;1  TagInspector Status

Now your ROOT file contains both the old histograms from QExample, and the new histograms from ParmExample.

Take a look a the number-of-track histograms:

root[] h1d3->Draw();
root[] h1d5->Draw();

Tracks-per-event histograms

and the momentum histograms:

root[] h1d4->Draw();
root[] h1d6->Draw();

Momentum histograms

The default settings for ParmExample are the same as the settings for QExample. So if you had not modified the run-time parameters in your Framework session, then the histograms would have been identical.

However, you can see that your changes did indeed have an effect. Now the momentum histogram limits are from -1.5 to 1.5 - not a very useful setting, since there are no tracks with negative momentum! Instead of 25 bins, now there are 100. And because you switched to the GoodTracksLoose list, there are 314 entries instead of 459, and the momentum distribution itself is different.

As for the number-of-tracks histograms, they are also different due to the use of GoodTracksLoose instead of ChargedTracks.

Fortunately, now that your parameters are run-time parameters, you can easily change the number of bins and the axes limits to reasonable values, and investigate many different particle candidate lists - all without having to recompile or relink your code!


Back to Workbook Front Page

Send comments to Workbook Team.