Tool Creation and Management

Last update: 14 Nov 2022 [History] [Edit]

Tools are possibly the most common way we distribute software components in ATLAS. In many respects it acts like a regular C++ object, but it fits in with the ATLAS software model.

As an example, let’s add the GoodRunsLists tool to our analysis. This tool will check whether a given data event can be used or was in a problematic luminosity block that is not suitable for use in analysis. The exact details are not that important here, we are using it because it makes for a simple example. The general outline will be the same for all tools.

If this example seems rather complicated for something that ought to be rather simple, it’s because it is. This mechanism is meant for much more complicated scenarios, and for something so simple you could come up with a simpler mechanism, but this can lead to problems later as your code increases in complexity.

The ToolHandle Class

One important thing about using tools is that you don’t create (or destroy) them directly inside your algorithm class. Instead the user/framework creates and configures the tools for you and then makes them available to your algorithm. For that to work properly your algorithm needs to refer to the tool using a ToolHandle. In many respects a ToolHandle works just like a (smart) pointer to the tool, except for some extra features related to configuration.

To use this tool we need the tool interface class IGoodRunsListSelectionTool and the xAOD::EventInfo class that holds the data we operate on. For that add AsgAnalysisInterfaces and to the LINK_LIBRARIES fields in your CMakeLists.txt file.

To use the tools with a ToolHandle you have to add the proper includes to the header file (MyxAODAnalysis.h) near the top:

// GRL
#include <AsgAnalysisInterfaces/IGoodRunsListSelectionTool.h>
#include <AsgTools/ToolHandle.h>

warning You should not try to forward declare the tool interface, but always include the proper header file.

And then add the ToolHandle inside the class itself:

  ToolHandle<IGoodRunsListSelectionTool> m_grl;

Inside the constructor you then have to setup the ToolHandle so that the framework can find and configure it:

MyxAODAnalysis :: MyxAODAnalysis (const std::string& name,
                                  ISvcLocator *pSvcLocator)
  : EL::AnaAlgorithm (name, pSvcLocator),
    m_grl ("GoodRunsListSelectionTool/grl", this)
  // declare the tool handle as a property on the algorithm
  declareProperty ("grlTool", m_grl, "the GRL tool");

The ToolHandle constructor takes two arguments: The first is the type and the name of the tool to be created, separated by a /. If you omit the / the assumption is that you want both of them to be the same. The second argument is a pointer to the parent, which indicates that you want to crate a private tool, i.e. a tool that is only owned/known by the parent. By and large you should make all your tool private tools (with some noteable exceptions). If you omit the last parameter your tool becomes a public tool, meaning it is shared by all tool handles that specify the same name.

The declareProperty call declares the ToolHandle as a property on the algorithm, which allows to configure it from python. It work pretty much the same as regular property declaration, though the configuration works somewhat differently (see below).

Within the initialize method you should then retrieve the tool, which is not strictly necessary, but it is recommended to make sure the tool is actually there before the job starts:

  ANA_CHECK (m_grl.retrieve());

warning Most tools will also have declared an initialize method. It is important that you do not call this method yourself. It will already have been called and some tools can break if it gets called twice. Unfortunately there are essentially no checks against you doing that, so you just have to make sure not to do that.

Using the Tool Itself

Next let’s actually use the tool. This part is very specific to the tool itself, whereas the above is essentially just boiler-plate code that will look more or less the same for all tools.

In the execute() method, after retrieving the `EventInfo object, check if the event is in fact a data event, and if it is, then check the GRL for this event:

  // Event information
  const xAOD::EventInfo* eventInfo = 0;
  ANA_CHECK(evtStore()->retrieve( eventInfo, "EventInfo"));  
  // check if the event is data or MC
  // (many tools are applied either to data or MC)
  bool isMC = false;
  // check if the event is MC
  if (eventInfo->eventType (xAOD::EventInfo::IS_SIMULATION)) {
    isMC = true; // can do something with this later

  // if data check if event passes GRL
  if (!isMC) { // it's data!
    if (!m_grl->passRunLB(*eventInfo)) {
      ANA_MSG_INFO ("drop event: GRL");
      return StatusCode::SUCCESS; // go to next event
  } // end if not MC

  ANA_MSG_INFO ("keep event: GRL");

The message statement is mostly so that we can see what is happening. For actual analysis you would either remove that statement or set it to DEBUG or even VERBOSE message level.

tip You may notice that sometimes we say m_grl. and sometimes m_grl->. The rule is that until the tool is initialized we are talking to the tool handle and use m_grl. after the tool is initialized we mostly talk to the tool itself and use m_grl-> instead.

You can now compile your code to make sure you didn’t make any mistakes in the code itself, but it won’t run (correctly) yet as the tool needs to be configured.

Getting the appropriate GRL

Since we are using the GRL selector tool, we need to have a good runs list for it to refer to. The complete set of GRLs can be found on the ATLAS DQM page. If you click on one of the GRLs, you will see information summarizing the runs in the list. You can also download the GRL using the wget command:


For this tutorial, however, the GRL is already available in ALRB_TutorialData.

Configuring the Tool

As noted above, your tool actually gets configured inside the python configuration file and then EventLoop will create it for you. Let’s do that now. There are actually multiple ways of doing this, we prefer the way below.

Just add the following to your configuration file after you create your algorithm and before you add it to the sequence/job (if you add multiple tools, you only need the import statement once):

from AnaAlgorithm.DualUseConfig import addPrivateTool

# add the GRL tool to the algorithm
addPrivateTool( alg, 'grlTool', 'GoodRunsListSelectionTool' )

# configure the properties of the GRL tool
fullGRLFilePath = os.getenv ("ALRB_TutorialData") + "/data16_13TeV.periodAllYear_DetStatus-v89-pro21-01_DQDefects-00-02-04_PHYS_StandardGRL_All_Good_25ns.xml"
alg.grlTool.GoodRunsListVec = [ fullGRLFilePath ]
alg.grlTool.PassThrough = 0 # if true (default) will ignore result of GRL and will just pass all events

We won’t discuss the actual property values here, but a couple of words on the addPrivateTool call: This takes three arguments, the algorithm the tool belongs to, and the name of the tool class. If you have keen eyes you may have noticed that this is different from the class you used in the C++ section. Essentially (almost) every tool has two classes, an interface class (usually starting with I) and an implementation class (usually the same name without the I in the beginning). In your C++ code you should only be using the interface class which contains all the functions the user can call and nothing else. In the configuration you will however have to specify the actual implementation class which contains the actual tool code.

Now compile and run your code and see if it does what you expect.