FinalExercise

From Atlas Wiki
Revision as of 16:56, 30 October 2006 by Zkestere (talk | contribs)
Jump to navigation Jump to search

Introduction

The goal of this exercise is to combine the skills needed for the previous exercises into one final assignment. After finishing this assignment, you've shown that you're able to create your own Tool, to use an Algorithm and configure it with jobOptions. You're skilled in using the important services such as messageSvc, toolSvc and storeGateSvc. Undefinately you are now an expert in using LXR and CVSview and you understand the structure of packages. Not bad!

The lines in this example only contain the bare necessities of the change in the code, not the full file. The includes and use-statements in the requirementsfile are not shown but should definately be added as well. Since those lines are not the prime issues of the assignment, these are not shown.

To obtain a tar file with the full exercise covered, go to the [FinalExercise].

Up till now

If you've modified ExampleAlg as explained in the previous exercise, ExampleAlg now has acces to DummyTracks which are stored in the collection DummyTrackCollection. This will be our starting point. A logical way to proceed is:

  • modify the IToolExample such that it has a method able to handle DummyTracks.
  • modify the ToolExample accordingly.
  • copy the ToolExample into another class ToolExampleSimple (don't forget to make the factory too).
  • create a new property for the ExampleAlg (in both the jobOptions and class).
  • implement the two ToolExample's method.

IToolExample

The IToolExample must have a method taking a DummyTrack to process, since the concrete implementations of the ToolExample(s) will have the method too. The IToolExample will have the following lines added:

 1 class DummyTrack;
 2 class IToolExample : virtual public IAlgTool {
      ...
 3    virtual StatusCode handleTrack(const DummyTrack* track) const = 0; 
 4 };

Line 1 is a forward declaration so that the class will recognize the DummyTrack class. The method on line 3 is the method taking the DummyTrack and both ToolExamples will implement this method. Note the '= 0' after the method, denoting that the method is pure abstract and requires a concrete implementation.

ToolExample

One ToolExample will just dump the trackparameters, the other will store HepPoints with the position and direction of the tracks. In this ToolExample we'll discuss the latter. The headerfile needs to follow the interface with the method, so in ToolExample.h:

 1 class ToolExample : public AlgTool, virtual public IToolExample {
      ...
 2    StatusCode handleTrack(const DummyTrack* track) const ; 
 3 };

The implementation of the method will be done in the sourcefile ToolExample.cxx:

 1 #include "AlgorithmExample/DummyTrack.h"
 2 #include "CLHEP/Geometry/Point3D.h"
   ...
 3 StatusCode ToolExample::handleTrack(const DummyTrack* track) const {
 4 Point3D position( ... );
 5 Point3D location( ... );
 6 MsgStream log(msgSvc(), name());
 7 log << MSG::INFO << "position = (" << position.x() << ", " 
                                      << position.y() << ", "
                                      << position.z() << ", )" << endreq;
 8 return StatusCode::SUCCESS;

ToolExampleSimple

The simple ToolExample doesn't convert the parameters to a position and direction, but just puts them to output. Just a copy of the previous ToolExample and rewriting all 'ToolExample' to 'ToolExampleSimple' will do it, and the implementation of the method itself should be different.

For the headerfile ToolExampleSimple:

 1 class ToolExampleSimple : public AlgTool, virtual public IToolExample {
      ...
 2    StatusCode handleTrack(const DummyTrack* track) const ; 
 3 };

This tools inherits from IToolExample, just like ToolExample. The implementation of the method will be done in the sourcefile ToolExampleSimple.cxx:

 1 #include "AlgorithmExample/DummyTrack.h"
   ...
 2 StatusCode ToolExampleSimple::handleTrack(const DummyTrack* track) const {
 3   MsgStream log(msgSvc(), name());
 4   log << MSG::INFO << "DummyTrack has the following parameters: " << endreq;
 5   log << MSG::INFO << "    d0 = " << track->d0()     << endreq;
 6   log << MSG::INFO << "    z0 = " << track->z0()     << endreq;
 7   log << MSG::INFO << " theta = " << track->theta()  << endreq;
 8   log << MSG::INFO << "   phi = " << track->phi()    << endreq;
 9   log << MSG::INFO << "qOverP = " << track->qOverP() << endreq;
10   return StatusCode::SUCCESS;
11 };

Finally, don't forget to add the ToolExampleSimple in the factory-entries file (src/components/AlgorithmExample_entries.cxx).

ExampleAlg and properties

The ExampleAlg already has created an instance of StoreGate in its ExampleAlg::initialize(). Not only will this algorithm have a property which holds a string to the location of the DummyTrackCollection, we will create an extra property in order to toggle between the two ToolExamples.

So, in the headerfile we still have the declaration of the IToolExample (and we add a bool to toggle the ToolExamples):

 1 class StoreGateSvc;
 2 class IToolExample;
 3 class DummyTrackCollection;
 4 class ExampleAlg : public Algorithm {
     ...
 5   private:
 6    const IToolExample*   m_tool;                 //instance of the Tool interface
 7    StoreGateSvc*         m_storeGate;            //instance of StoreGateSvc
 8    DummyTrackCollection* m_tracks;               //TrackCollection to store tracks in
 9    std::string           m_collectionLocation;   //property: location of the collection in StoreGate
10    bool                  m_doSimple;             //property: switch to toggle between ToolExamples
11 };

The sourcefile has adjustments in its constructor:

 1 ExampleAlg::ExampleAlg(const std::string& name, ISvcLocator* pSvcLocator) :
 2  Algorithm(name, pSvcLocator), m_storeGate(0), m_tracks(0), m_collectionLocation(""), m_doSimple(true) {
 3    declareProperty("collectionLocation", m_collectionLocation);
 4    declareProperty("doSimple"          , m_doSimple);
 5  }

Line 2 calls the constructors of the members of ExampleAlg. In line 3 and 4, the properties are declared. In the initialization phase, we use the switch for the Tool:

 1 StatusCode ExampleAlgorithm::initialize() {
     ...
 2   StatusCode sc;
 3   if( m_doSimple )
 4     sc = toolSvc()->retrieveTool("ToolExampleSimple",m_tool);
 5   else
 6     sc = toolSvc()->retrieveTool("ToolExample",m_tool);
 7   if(sc.isFailure()) {
 8     log << MSG::ERROR << "ToolSvc could not retrieve ToolExample" << endreq;
 9     return sc;
10   } else log << MSG::INFO << "ToolSvc retrieved ToolExample" << endreq;
11   return sc;
12 }

Line 3 contains the switch between the ToolExamples. The only difference is the first argument of the retrieveTool method of the ToolService! Of course, there is still the construction checking wether the Tool was correctly retrieved (line 7).

Finally, you should set the properties in the pythonscript (share/AlgorithmExample.py):

 1 ExampleAlg = Algorithm( "ExampleAlg" )
 2 ExampleAlg.collectionLocation = "DummyTrackCollection"
 3 ExampleAlg.doSimple = False

Line 1 creates a variable ExampleAlg which can be used to set the properties with, line 2 sets the DummyTrackCollection location and the last line toggles between the different Tools.

Check your ATHENA output to see if the Algorithm (and the Tool) behaves as expected.