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.
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>
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 (in MyxAODAnalysis.cxx
) 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());
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.
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.
You may notice that sometimes we say
m_grl.
and sometimesm_grl->
. The rule is that until the tool is initialized we are talking to the tool handle and usem_grl.
after the tool is initialized we mostly talk to the tool itself and usem_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.
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:
wget http://atlasdqm.web.cern.ch/atlasdqm/grlgen/All_Good/data16_13TeV.periodAllYear_DetStatus-v89-pro21-01_DQDefects-00-02-04_PHYS_StandardGRL_All_Good_25ns.xml
For this tutorial, however, the GRL is already available in ALRB_TutorialData
.
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.