Example: Light Taper Implemented in CalDigi
Light taper is the decay of light in the crystals from the energy deposition point to the end face (and the diode). It is envisioned that multiple light taper functions will be available on demand and configurable from a jobOptions file. This can be done using Gaudi Tools.
Input. As input, the light taper takes the position and magnitude of the energy deposit; parameters are then used to calculate attenuation.
Initial taper models are: linear (simple, default so far) and linear+exponential, which empirically reproduces the drop-off of light collection observed near the end faces and yields a slightly
S-shaped light asymmetry curve.
Implementation
The following is the minimal checklist for code necessary when developing a Gaudi Tool, taken from of the Gaudi Developers Guide, page 114:
1. Define specific interface (inheriting from the IAlgTool interface).
2. Derive tool class from the AlgTool base class
3. Provide constructor
4. Declare additional interface in the constructor.
5. Implement the factory adding the lines of code shown in Listing 12.4
6. Implement specific interface methods.
Note: If a tool requires special initialization and termination you can also implement the initialize and finalize methods. Abstract Interface Class - ITaper
An interface class, ITaper, was defined to encapsulate the taper function behaviour. It inherits from IAlgTool.
class ITaper : virtual public IAlgTool
It has a standard default constructor and destructor, plus additional code for the Tool interface:
a global object:
static const InterfaceID IID_ITaper("ITaper", 1 , 0);
and in the public definition:
static const InterfaceID& interfaceID() { return IID_ITaper; }
So far, it's only function of physical interest is
calculateSignals(double relativePosition, double energyDeposit)
which is set up as a pure virtual function.
Concrete Implementation - LinearTaper
The concrete implementation inherits from both AgTools and ITaper
class LinearTaper : public AlgTool, virtual public ITaper
with special constructor
LinearTaper( const std::string& type, const std::string& name, const IInterface* parent);
and declaration of the to-be-overriden calculateSignals function:
virtual std::pair<double, double> calculateSignals(double relativePosition, double depositedEnergy);
In the implementation file, one has to implement the factories
#include "GaudiKernel/ToolFactory.h"
static ToolFactory<linearTaper> s_factory;
const IToolFactory& linearTaperFactory = s_factory;
LinearTaper::LinearTaper( const std::string& type,
const std::string& name,
const IInterface* parent)
: AlgTool(type,name,parent)
{
// declare base interface for all consecutive concrete classes
declareInterface<ITaper>(this);
}
Note: Concrete implementations can override the initialize() function and can have their own extended private data, so they can be quite different in practical application (use of parameters, internal data, etc).
Declaring the Tool Name
As is required for Algorithms, it is necessary to tell the system about the name of the tool. This is done in CalDigi_load.cxx (note - this also includes the already existing declaration of the CalDigiAlg algorithm):
#include "GaudiKernel/DeclareFactoryEntries.h"
#include "GaudiKernel/IToolFactory.h"
#define DLL_DECL_TOOL(x) extern const IToolFactory& x##Factory; x##Factory.addRef();
DECLARE_FACTORY_ENTRIES(CalDigi) {
DECLARE_ALGORITHM( CalDigiAlg );
DLL_DECL_TOOL( LinearTaper );
}
Retrieving the Tool
The tool is currently used from CalDigiAlg. A pointer is maintained in the private data:
ITaper* m_taper;
referencing only the base class, as desired for interchangeability.
And the Tool is retrieved via the toolSvc function from CalDigiAlg's initialize() function:
sc = toolSvc()->retrieveTool("LinearTaper",m_taper);
if (sc.isFailure() ) {
log << MSG::ERROR << " Unable to create LinearTaper tool" << endreq;
return sc;
}
Note that one must include the IToolSvc.h file (not sure why since this is notionally in the Algorithm interface?):
#include "GaudiKernel/IToolSvc.h"
Accessing the Tool
The tool is used in the CalDigiAlg::execute() loop where McIntegratingHits are found and energy (and moments) are used to calculate the light attenuation:
std::pair<double,double> signals;
signals = m_taper->calculateSignals(relpos,ene);
// set up a XtalMap to act as key for the map - if there is no entry, add
// add one, otherwise add signal to existing map element.
xtalSignalRef.addSignal(signals.first,signals.second);
We have achieved the desired effect of being able to select the type of calculateSgnals function external to its use. It can now be set up via a jobOptions parameter to CalDigiAlg.
Owned by: Richard Dubois
Last updated by: Chuck Patterson
07/29/2005 |
|
|