RandomSelectUserObjects.hpp

Go to the documentation of this file.
00001 /* File RandomSelectUserObjects.hpp
00002  *
00003  * Created       : Sun May 31 2007
00004  * Author        : Amnon Harel (but most of the code is a copy of SelectUserObjects)
00005  * Purpose       : Base class for cafe object selectors that use random numbers
00006  * Last modified : 
00007  * Comments      : Use this instead of a multiplie inheritence from SelectUserObjects and RandomProcessor
00008 
00009     See SelectUserObjects for the main parameters.
00010 
00011     See RandomProcessor for parameters controling the random behavior.
00012 
00013   Usage :
00014 
00015    In the header file
00016    ------------------
00017    class yourProcessor : public cafe::RandomSelectUserObjects<T> { // Do not also inherit from Processor!
00018 
00019      where T is the type of objects you're selecting
00020 
00021    In the source flie
00022    ------------------
00023    1) Call the base constructor:
00024 
00025      yourProcessor::yourProcessor (const char *name) : 
00026        cafe::RandomSelectUserObjects<T>(name)
00027 
00028    2) In your processEvent method, you must call the base class explicitely when you want it to
00029       loop over the objects and call your selectObject method.
00030 
00031      bool yourProcessor::processEvent(cafe::Event& event)
00032      {
00033        cafe::RandomSelectUserObjects<T>::processEvent (event);
00034 
00035        TRandom& rnd = myTRandom();
00036        ...
00037 
00038      or simply call myRand().Uniform() etc.
00039 
00040    2a) If you need random numbers in your processEvent before looping on the objects, 
00041        you can call the RandomProcessor::processEvent explicitely, but take care to somehow change
00042        the resulting seed, otherwise you'll have a nasty correlation when it's reinitialized
00043        in the later call to RandomSelectUserObjects<T>::processEvent.
00044 
00045    3) if you implement inputFileOpened, you must call the base class explicitely (preferably the first thing
00046    in your function):
00047 
00048      yourProcessor::inputFileOpened (TFile* file)
00049      {
00050        cafe::RandomSelectUserObjects<T>::inputFileOpened (file);
00051        ...
00052 
00053    4) same for inputFileClosing
00054 
00055      yourProcessor::inputFileClosing (TFile* file)
00056      {
00057        cafe::RandomSelectUserObjects<T>::inputFileClosing (file);
00058        ...
00059 
00060        Caveats: See 2a) above.
00061 
00062     \ingroup group_cafe
00063  */
00064 
00065 #ifndef RandomSelectUserObjects_HPP_
00066 #define RandomSelectUserObjects_HPP_
00067 
00068 #include "cafe/Event.hpp"
00069 #include "cafe/Processor.hpp"
00070 #include "cafe/Config.hpp"
00071 #include "cafe/Variables.hpp"
00072 
00073 #include "TFile.h"
00074 #include "TTree.h"
00075 #include "TBranch.h"
00076 #include "TBranchElement.h"
00077 #include "TDirectory.h"
00078 #include "TClonesArray.h"
00079 
00080 #include <stdexcept>
00081 
00082 #include "cafe/RandomProcessor.hpp"
00083 
00084 namespace cafe {
00085 
00086     template<class T> 
00087     class RandomSelectUserObjects : public RandomProcessor {
00088     public:
00089         RandomSelectUserObjects(const char *name);
00090         void inputFileOpened(TFile *file);
00091         void inputFileClosing(TFile *file);
00092         bool processEvent(cafe::Event& event);
00093     protected:
00098         virtual bool selectObject(const T& obj) = 0;
00099     
00102         virtual void before(Collection<T>& from);
00103     
00105         virtual void after(Collection<T>& accepted, Collection<T>& rejected);
00106     
00108         void addVariable(const std::string& name) {_vars.add(name);}
00109 
00110     private:
00111         std::string  _fromBranch;
00112         std::string  _toBranch;
00113         std::string  _toRejectedBranch;
00114         std::string  _treeName;      
00115         TTree        *_tree;
00116         TClonesArray *_result;
00117         TClonesArray *_resultRejected;
00118         TBranch      *_branch;
00119         TBranch      *_branchRejected;
00120         Variables     _vars;
00121     public:
00122         ClassDef(RandomSelectUserObjects, 0);
00123     };
00124 
00125     // 
00126     // Templated implementation must go here...
00127     // 
00128     
00129     template<class T>
00130     RandomSelectUserObjects<T>::RandomSelectUserObjects(const char *name)
00131         : RandomProcessor(name), 
00132           _tree(0),
00133           _result(0),
00134           _resultRejected(0),
00135           _branch(0),
00136           _branchRejected(0)
00137     {
00138         using namespace cafe;
00139 
00140         // read this from configuration file
00141         Config config(name);
00142 
00143         _fromBranch = config.get("From", "");
00144         _toBranch   = config.get("To", "");
00145         _toRejectedBranch   = config.get("RejectedBranch", "");
00146         _treeName   = config.get("Tree", "TMBTree");
00147         // need to explicitely convert from std::vector<std::string> to Variables before copy constructor
00148         _vars       = Variables (config.getVString("Variables", " ,"));
00149         if(_fromBranch.empty()) {
00150             throw std::runtime_error(std::string("RandomSelectUserObjects[") + name
00151                                      + "] : From: branch in config file not set");
00152         }
00153 
00154         if(_toBranch.empty()) {
00155             throw std::runtime_error(std::string("RandomSelectUserObjects[") + name
00156                                      + "] : To: branch in config file not set");
00157         }
00158 
00159         if(_fromBranch == _toBranch) {
00160             throw std::runtime_error(std::string("RandomSelectUserObjects[") + name
00161                                      + "] : From: branch has the same name as To: branch");
00162         }
00163 
00164         if(_fromBranch == _toRejectedBranch) {
00165             throw std::runtime_error(std::string("RandomSelectUserObjects[") + name
00166                                      + "] : From: branch has the same name as RejectedBranch: branch");
00167         }
00168 
00169         out() << "RandomSelectUserObjects[" << name << "] From: " << _fromBranch 
00170               << " To: " << _toBranch << std::endl ;
00171         if (_toRejectedBranch != "") {
00172             out () << "  Rejected objects go to branch: " << _toRejectedBranch  << std::endl;
00173         }
00174         out() << "RandomSelectUserObjects[" << name << "] Output Tree: " << _treeName << std::endl;
00175     }
00176 
00177     template<class T>
00178     void RandomSelectUserObjects<T>::inputFileOpened(TFile *file)
00179     {
00180         RandomProcessor::inputFileOpened (file); // the timing of this call is immaterial
00181         if(TTree *tmb_tree = (TTree *)file->Get("TMBTree")) {
00182 
00183             if ( _treeName=="TMBTree" ) _tree = dynamic_cast<TTree*>(file->Get("TMBTree"));
00184             else _tree = dynamic_cast<TTree *>(gROOT->Get(_treeName.c_str()));
00185 
00186             if (_tree == 0) {
00187                 gROOT->cd();
00188                 _tree = new TTree(_treeName.c_str(), fullName().c_str());
00189                 tmb_tree->AddFriend(_tree);
00190             }
00191             
00192             _branch = _tree->GetBranch(_toBranch.c_str()) ;
00193             if (_branch == 0) {
00194                 if(TBranchElement *br = (TBranchElement *)tmb_tree->GetBranch(_fromBranch.c_str())) {
00195                     _result = new TClonesArray(br->GetClonesName());
00196                     _branch = _tree->Branch(_toBranch.c_str(), &_result, 4096);
00197                     if (_toRejectedBranch != "" && !_branchRejected) {
00198                         _resultRejected = new TClonesArray(br->GetClonesName());
00199                         _branchRejected = _tree->Branch(_toRejectedBranch.c_str(), &_resultRejected, 4096);                             }
00200                 } else {
00201                     err() << "RandomSelectUserObjects[" << name() << "] No such branch: " 
00202                           << _fromBranch << std::endl;
00203                 }
00204             }
00205         } else {
00206             err() << "RandomSelectUserObjects[" << name() << "] No TMBTree" << std::endl;
00207         }
00208     }
00209 
00210     template<class T>
00211     void RandomSelectUserObjects<T>::inputFileClosing(TFile *file)
00212     {
00213         
00214         if(TTree* oldtree =
00215            dynamic_cast<TTree *>(gROOT->Get(_treeName.c_str()))) {
00216             oldtree->Delete();
00217         }
00218         _tree = 0;
00219         _branch = 0;
00220         _branchRejected = 0;
00221     }
00222 
00223     template<class T>
00224     void RandomSelectUserObjects<T>::before(Collection<T>& from) 
00225     {
00226     }
00227     
00228     template<class T>
00229     void RandomSelectUserObjects<T>::after(Collection<T>& accepted, Collection<T>& rejected) 
00230     {
00231     }
00232     
00233     template<class T>
00234     bool RandomSelectUserObjects<T>::processEvent(cafe::Event& event)
00235     {
00236         using namespace cafe;
00237 
00238         RandomProcessor::processEvent (event); // done first, so PRNs are available in the user's selectObject method
00239 
00240         if(!_result) return true;
00241         _result->Delete() ;
00242         if(_resultRejected) _resultRejected->Delete() ;
00243 
00244         Collection<T> from(event.getCollection<T>(_fromBranch.c_str(), _vars));
00245         
00246         before(from);
00247 
00248         Int_t next = 0;
00249         Int_t nextr = 0;
00250 
00251         for(typename Collection<T>::const_iterator it = from.begin();
00252             it != from.end();
00253             ++it) {
00254             if(selectObject(*it)) {
00255                 event.readBranch(_fromBranch);
00256                 new ((*_result)[next++]) T(*it); 
00257             } else if (_resultRejected) {
00258                 event.readBranch(_fromBranch);
00259                 new ((*_resultRejected)[nextr++]) T(*it); 
00260             }
00261         }
00262 
00263         Collection<T> accepted(_result);
00264         Collection<T> rejected(_resultRejected);
00265         
00266         after(accepted, rejected);
00267 
00268         return true;
00269     }
00270  
00271 } // end namespace
00272 
00273 #endif

Generated on Thu Apr 3 04:14:23 2008 for CAF by doxygen 1.3.4