Tools are light weight objects whose purpose is to help other components perform their work. A framework service, the
ToolSvc
, is responsible for creating and managing Tools. An
Algorithm
requests the tools it needs to the ToolSvc, specifying if requesting a private instance by declaring itself as the parent. Since Tools are managed by the ToolSvc, any component1 can request a tool. Only Algorithms and Services can declare themselves as Tools parents.
In this chapter we first describe these objects and the difference between "private" and "shared" tools. We then look at the
AlgTool
base class and show how to write concrete Tools.
In section 12.3 we describe the
ToolSvc
and show how a component can retrieve
Tools
via the service.
Finally we describe Associators, common utility
GaudiTools
for which we provide the interface and base class.
As mentioned elsewhere Algorithms make use of framework services to perform their work. In general the same instance of a service is used by many algorithms and Services are setup and initialized once at the beginning of the job by the framework. Algorithms also delegate some of their work to sub-algorithms. Creation and execution of sub-algorithms are the responsibilities of the parent algorithm whereas the initialize() and finalize() methods are invoked automatically by the framework while initializing the parent algorithm. The properties of a sub-algorithm are automatically set by the framework but the parent algorithm can change them during execution. Sharing of data between nested algorithms is done via the Transient Event Store.
Both Services and Algorithms are created during the initialization stage of a job and live until the jobs ends.
Sometimes an encapsulated piece of code needs to be executed only for specific events, in which case it is desirable to create it only when necessary. On other occasions the same piece of code needs to be executed many times per event. Moreover it can be necessary to execute a sub-algorithm on specific contained objects that are selected by the parent algorithm or have the sub-algorithm produce new contained objects that may or may not be put in the Transient Store. Finally different algorithms may wish to configure the same piece of code slightly differently or share it as-is with other algorithms.
To provide this kind of functionality we have introduced a category of processing objects that encapsulate these "light" algorithms. We have called this category Tools.
Some examples of possible tools are single track fitters, association to Monte Carlo truth information, vertexing between particles, smearing of Monte Carlo quantities.
Algorithms
can share instances of
Tools with other Algorithms
if the configuration of the tool is suitable. In some cases however an
Algorithm
will need to customize a tool in a specific way in order to use it. This is possible by requesting the
ToolSvc
to provide a
"private"
instance of a tool.
If an
Algorithm
passes a pointer to itself when it asks the
ToolSvc
to provide it with a
tool
, it is declaring itself as the parent and a
"private"
instance is supplied. Private instances can be configured according to the needs of each particular
Algorithm
via jobOptions.
As mentioned above many
Algorithms
can use a tool
as-is
, in which case only one instance of a
Tool
is created, configured and passed by the
ToolSvc
to the different algorithms. This is called a
"shared"
instance. The parent of "shared" tools is the
ToolSvc
.
The main responsibilities of the
AlgTool
base class (see Listing 62) are the identification of the tools instances, the initialisation of certain internal pointers when the tool is created and the management of the tools properties. The
AlgTool
base class also offers some facilities to help in the implementation of derived tools.
serviceLocator()
method is provided to enable the derived tools to locate the services necessary to perform their jobs. Since concrete
Tools
are instantiated by the
ToolSvc
upon request, all Services created by the framework prior to the creation of a tool are available. In addition access to the message service is provided via the
msgSvc()
method. Both pointers are retrieved from the parent of the tool.
Algorithms
is provided. This allows tuning of data members used by the Tools via JobOptions files. The
ToolSvc
takes care of calling the
setProperties()
method of the
AlgTool
base class after having instantiated a tool. Properties need to be declared in the constructor of a
Tool
. The property
outputLevel
is declared in the base class and is identically set to that of the parent component. For details on Properties see section 11.3.1.
IInterface
of the parent component. The name is used for the identification of the tool instance as described below.The parent interface is used by the tool to access for example the
outputLevel
of the parent.
IAlgTool
Interface -A tool instance is identified by its full name. The name consist of the concatenation of the parent name, a dot, and a tool dependent part. The tool dependent part can be specified by the user, when not specified the tool type (i.e. the class) is automatically taken as the tool dependent part of the name. Examples of tool names are RecPrimaryVertex.VertexSmearer (a private tool) and ToolSvc.AddFourMom (a shared tool). The full name of the tool has to be used in the jobOptions file to set its properties.
Operational functionalities of tools must be provided in the derived tool classes. A concrete tool class must inherit directly or indirectly from the AlgTool base class to ensure that it has the predefined behaviour needed for management by the
ToolSvc
. The inheritance structure of derived tools is shown in Figure 24.
ConcreteTool1
implements one additional abstract interface while
ConcreteTool3
and
ConcreteTool4
derive from a base class
SubTool
that provides them with additional common functionality.
|
The idea is that concrete tools could implement additional interfaces, specific to the task a tool is designed to perform. Specialised tools intended to perform similar tasks can be derived from a common base class that will provide the common functionality and implement the common interface. Consider as example the vertexing of particles, where separate tools can implement different algorithms but the arguments passed are the same. If a specialized tool is only accessed via the additional interface, the interface itself must inherit from the
IAlgTool
interface in order for the tool to be correctly managed by the
ToolSvc
.
An example minimal implementation of a concrete tool is shown in Listing 63 and Listing 64, taken from the
ToolsAnalysis
example application distributed with the Gaudi framework..
The creation of concrete tools is similar to that of Algorithms, making use of a Factory Method. As for Algorithms, Tool factories enable their creator to instantiate new tools without having to include any of the concrete tools header files. A template factory is provided and a tool developer will only need to add the concrete factory in the implementation file as shown in lines 1 to 4 of Listing 64
In addition a concrete tool class must specify a single constructor with the same parameter signatures as the constructor of the
AlgTool
base class as shown in line 5 of Listing 63.
Below is the minimal checklist of the code necessary when developing a Tool:
In addition if the tool is implementing an additional interface you may need to:
The
ToolSvc
manages
Tools
. It is its responsibility to create tools and make them available to
Algorithms
or
Services
.
The
ToolSvc
verifies if a tool type is available and creates the necessary instance after having verified if it doesn't already exist. If a tool instance exists the
ToolSvc
will not create a new identical one but pass to the algorithm the existing instance. Tools are created on a "first request" basis: the first Algorithm requesting a tool will prompt its creation. The relationship between an algorithm, the ToolSvc and Tools is shown in Figure 25.
|
The
ToolSvc
will "hold" a tool until it is no longer used by any component or until the
finalize()
method of the tool service is called. Algorithms can inform the
ToolSvc
they are not going to use a tool previously requested via the
releaseTool
method of the
IToolSvc
interface2.
The
ToolSvc
is created by default by the
ApplicationMgr
and algorithms wishing to use the service can retrieve it using the
service
accessor method of the
Algorithm
base class as shown in the lines below.
include "Gaudi/Interfaces/IToolSvc.h"...IToolSvc* toolSvc=0;StatusCode sc = service( "ToolSvc",toolSvc);if ( sc.isFailure) { ... |
IToolSvc
interface
The
IToolSvc
interface is the
ToolSvc
specific interface providing methods to retrieve
tools
. The interface has two
retrieve
methods that differ in their parameters signature, as shown in Listing 65
The arguments of the method shown in Listing 65, line 1, are the tool
type
(i.e. the class) and the
IAlgTool
interface of the returned tool. In addition there are two arguments with default values: one is the
IInterface
of the component requesting the tool, the other a boolean creation flag. If the component requesting a tool passes a pointer to itself as the third argument, it declares to the
ToolSvc
that is asking a "private" instance of the tool. By default a "shared" instance is provided. In general if the requested instance of a Tool does not exist the ToolSvc will create it. This behaviour can be changed by setting to
false
the last argument of the method.
The method shown in Listing 65, line 2 differs from the one shown in line 1 by an extra argument, a string specifying the tool dependent part of the full tool
name
. This enables a component to request two separately configurable instances of the same tool.
To help the retrieval of concrete tools two template functions, as shown in Listing 66, are provided in the
IToolSvc
interface file.
The two template methods correspond to the
IToolSvc
retrieve methods but have the tool returned as a template parameter. Using these methods the component retrieving a tool avoids explicit dynamic-casting to specific additional interfaces or to derived classes.
Listing 67 shows an example of retrieval of a shared and of a common tool.
1:
IToolSvc* toolsvc = 0;
2:
sc = service( "ToolSvc", toolsvc );
3:
if( sc.isFailure() ) {
4:
log << MSG::FATAL << " Unable to locate Tool Service" << endreq; return sc;
5:
}
6:
// Example of tool belonging to the ToolSvc and shared between
7:
// algorithms
9:
if( sc.isFailure() ) {
10:
log << MSG::FATAL << " Unable to create AddFourMom tool" << endreq;
11:
return sc;
12:
}
13:
// Example of private tool
15:
if( sc.isFailure() ) {
16:
log << MSG::FATAL << " Unable to create ImpactPar tool" << endreq;
17:
return sc;
18:
} |
In general concrete tools are specific to applications or detectors' code but there are some tools of common utility for which interfaces and base classes can be provided. The
Associators
described below and contained in the
GaudiTools
package are one of such tools.
When working with Monte Carlo data it is often necessary to compare the results of reconstruction or physics analysis with the original corresponding Monte Carlo quantities on an event-by-event basis as well as on a statistical level.
Various approaches are possible to implement navigation from reconstructed simulated data back to the Monte Carlo truth information. Each of the approaches has its advantages and could be more suited for a given type of event data or data-sets. In addition the reconstruction and physics analysis code should treat simulated data in an identical way to real data.
In order to shield the code from the details of the navigation procedure, and to provide a uniform interface to the user code, a set of Gaudi Tools, called Associators , has been introduced. The user can navigate between any two arbitrary classes in the Event Model using the same interface as long as a corresponding associator has been implemented. Since an Associator retrieves existing navigational information, its actual implementation depends on the Event Model and how the navigational information is stored. For some specific Associators, in addition, it can depend on some algorithmic choices: consider as an example a physics analysis particle and a possible originating Monte Carlo particle where the associating discriminant could be the fractional number of hits used in the reconstruction of the tracks. An advantage of this approach is that the implementation of the navigation can be modified without affecting the reconstruction and analysis algorithms because it would affect only the associators. In addition short-cuts or complete navigational information can be provided to the user in a transparent way. By limiting the use of such associators to dedicated monitoring algorithms where the comparison between raw/reconstructed data and MC truth is done, one could ensure that the reconstruction and analysis code treat simulated and real data in an identical way.
Associators must implement a common interface called
IAssociator
. An
Associator
base class providing at the same time common functionality and some facilities to help in the implementation of concrete Associators is provided. A first version of these classes as well as an example of a concrete implementation are provided in the current release of Gaudi.
IAssociator
Interface
As already mentioned Associators must implement the
IAssociator
interface.
In order for Associators to be retrieved from the
ToolSvc
only via the
IAssociator
interface, the interface itself inherits from the
IAlgTool
interface. While the implementation of the
IAlgTool
interface is done in the
AlgTool
base class that of the
IAssociator
interface is the full responsibility of concrete associators.
The four methods of the
IAssociator
interface that a concrete Associator must implement are show in Listing 68
Two
i_retrieveDirect
methods must be implemented for retrieving associated classes following the same direction as the links in the data: for example from reconstructed particles to Monte Carlo particles. The first parameter is a pointer to the object for which the associated Monte Carlo quantity(ies) is requested. The second parameter, the discriminating signature between the two methods, is one or a vector of pointers to the associated Monte Carlo objects of the type requested. Some reconstructed quantities will have only one possible Monte Carlo associated object of a certain type, some will have many, others will have many out of which a "best" associated object can be extracted. If one of the two methods is not valid for a concrete associator, such method must return a failure. The third and fourth parameters are the class IDs of the objects for which the association is requested. This allows to verify at run time if the objects' types are those the concrete associator has been implemented for.
The two
i_retrieveInverse
methods are complementary and are for retrieving the association between the same two classes but in the opposite direction to that of the links in the data: from Monte Carlo particles to reconstructed particles. The different name is intended to alert the user that navigation in this direction may be a costly operation
Four corresponding template methods are implemented in
IAssociator
to facilitate the use of Associators by Algorithms (see Listing 69). Using these methods the component retrieving a tool avoids some explicit dynamic-casting as well as the setting of class IDs. An example of how to use such methods is described in section 12.4.1.3.
An associator is a type of
AlgTool,
so the
Associator
base class inherits from the
AlgTool
base class. This allows for Associators to be created and managed as
AlgTools
by the
ToolSvc
. Since all the methods of the
AlgTool
base class as described in section 12.2.2.1 are available in the
Associator
base class, only the additional functionality is described here.
eventSvc()
method is provided to access the Event Data Service since most concrete associators will need to access data, in particular if accessing navigational short-cuts.
FollowLinks
" and "
DataLocation
". They are respectively a
bool
with initial value
true
and a
std::string
with initial value set to " ". The first is foreseen to be used by an associator when it is possible to either follow links between classes or retrieve navigational short cuts from the data. A user can choose to set either behaviour at run time. The second property contains the location in the data where the stored navigational information is located. Currently it must be set via the jobOptions when necessary, as shown in Listing 70 for particular implementation provided in the Associator example. Two corresponding methods are provided for using the information from these properties:
followLinks()
and
whichTable()
.
inverseExist
() and
setInverseFlag(bool)
help in keeping track of the status of the locally kept inverse information.The method
buildInverse
() has to be overridden by concrete associators since they choose in which form to keep the information and should be called by the associator when receiving the first request during the processing of an event.
Associator
base class implements the
IListener
interface and, in the constructor, register itself with the Incident Service (see section 11.9 for details of the Incident Service). The associator
'
s
flushCache
() method is called in the implementation of the
IListener
interface in the
Associator
base class. This method must be overridden by concrete associators wanting to do a meaningful reset of the their initial status.
With the current release of Gaudi an example implementation of a specific associator is provided in the
Associator
example of the
GaudiExamples
package. Some of the choices in the example are related to the specific classes for which the associator (
AxPart2MCParticleAsct
) has been implemented and on how the information is available in the data files and should be regarded as such.
The
AxPart2MCParticleAsct
provides association between physics analysis particles (
AxPartCandidate
) and the corresponding Monte Carlo particles (
MCParticle
). The direct navigational information is stored in the persistent data as short-cuts and is retrieved in the form of a
SmartRefTable
in the Transient Event Store. This choice is specific to
AxPart2MCParticleAsct
, any associator can use internally a different navigational mechanism. The location in the Event Store where the navigational information can be found is set in the jobOptions via the setting of the "
DataLocation
" property, as shown in Listing 70.
ToolSvc.AxPart2MCParticleAsct.DataLocation = "/Event/Anal/AxPart2MCParticle"; |
In the current LHCb data model only a single
MCParticle
can be associated to one
AxPartCandidate
and vice-versa only one or no
AxPartCandidate
can be associated to one
MCParticle
. For this reason only the
i_retrieveDirect
and
i_retrieveInverse
methods providing one-to-one association are meaningful. Both methods verify that the objects passed are of the
correct
type before attempting to retrieve the information, as show in Listing 71. When an association is not found a
StatusCode::FAILURE
is returned.
The
i_retrieveInverse
method providing the one-to-many association returns a failure, while a fake implementation of the one-to-many
i_retriveDirect
method is implemented in the example to show how an Algorithm can use such method. In the
AxPart2MCParticleAsct
example the inverse table is kept locally and both the
buildInverse
() and
flushCache
() methods are overridden. In the example the choice has been made to implement an additional method
buildDirect
() to retrieve the direct navigational information on a first request per event basis.
In Listing 72 it is shown how a
monitoring
Algorithm can get an associator from the
ToolSvc
and use it to retrieve associated objects through the template interfaces.