DefaultReconstructedParticleMaker.cxx

Go to the documentation of this file.
00001 // ================================================
00002 // DefaultReconstructedParticleMaker class Implementation
00003 // ================================================
00004 //
00005 // THIS TEXT TO BE REPLACED BY ATLAS STANDARD FORMAT
00006 //
00007 // Namespace Atlfast
00008 //
00009 
00010 #include "AtlfastAlgs/DefaultReconstructedParticleMaker.h"
00011 #include "AtlfastAlgs/ISmearerFactory.h"
00012 #include "AtlfastAlgs/GlobalEventData.h" 
00013 
00014 //#include "AtlfastAlgs/CorrectionFactor.h"
00015 
00016 #include "AtlfastAlgs/MuonAcceptor.h"
00017 
00018 #include "AtlfastEvent/MsgStreamDefs.h"
00019 #include "AtlfastEvent/MCparticleCollection.h"
00020 
00021 #include "AtlfastUtils/HeaderPrinter.h"
00022 #include "AtlfastUtils/HepMC_helper/IMCselector.h"
00023 #include "AtlfastUtils/HepMC_helper/SelectType.h"
00024 #include "AtlfastUtils/HepMC_helper/IsFinalState.h"
00025 #include "AtlfastUtils/HepMC_helper/IsFromHardScatter.h"
00026 #include "AtlfastUtils/HepMC_helper/MCCuts.h"
00027 #include "AtlfastUtils/HepMC_helper/NCutter.h"
00028 #include "AtlfastUtils/FunctionObjects.h"
00029 
00030 #include <cmath> 
00031 
00032 // Generic algorithms
00033 #include <algorithm>
00034 
00035 // Gaudi includes
00036 #include "GaudiKernel/DataSvc.h"
00037 
00038 // CLHEP,HepMC
00039 #include "GeneratorObjects/McEventCollection.h"
00040 #include "CLHEP/Units/SystemOfUnits.h"
00041 
00042 namespace Atlfast {
00043   using std::abs;
00044   using std::vector;
00045   using std::sort;
00046   //--------------------------------
00047   // Constructor 
00048   //--------------------------------
00049   
00050   DefaultReconstructedParticleMaker::DefaultReconstructedParticleMaker 
00051   ( const std::string& name, ISvcLocator* pSvcLocator )
00052     : Algorithm( name, pSvcLocator ),
00053       m_ncutter(0),
00054       m_smearer(0),
00055       m_acceptor(0),
00056       m_lnkReconstructedParticle(0),
00057       m_tesIO(0),
00058       m_log( messageService(), name )
00059   {
00060     
00061     // Set the parameter defaults.
00062     m_particleType      = 11;
00063     m_mcPtMin           = 0.0*GeV;
00064     m_mcEtaMax          = 100.0;
00065     m_PtMin             = 5.0*GeV;
00066     m_EtaMax            = 2.5;
00067     m_doSmearing        = true;
00068     m_muSmearKey        = 1;
00069     m_outputLocation    = "/Event/AtlfastReconstructedParticle" ;
00070     m_muonResFile       = "atlfastDatafiles/MuonResolutionTable.xml" ;
00071     m_smearParamSchema  = 1;
00072     m_applyEfficiencies = false;
00073     
00074     // Declare the parameters to Gaudi so that
00075     // they can be over-written via the job options file
00076     declareProperty( "ParticleType",     m_particleType ) ;
00077     declareProperty( "mcMinimumPt",      m_mcPtMin ) ;
00078     declareProperty( "mcMaximumEta",     m_mcEtaMax ) ;
00079     declareProperty( "MinimumPt",        m_PtMin ) ;
00080     declareProperty( "MaximumEta",       m_EtaMax ) ;
00081     declareProperty( "DoSmearing",       m_doSmearing ); 
00082     declareProperty( "OutputLocation",   m_outputLocation ) ;
00083     declareProperty( "MuonResFile",      m_muonResFile ) ;
00084     declareProperty( "MuonSmearKey",     m_muSmearKey ); 
00085     
00086     //cct: declare the smearing parameters and schema.
00087     // It is possible these JOs will not be found
00088     // (say, if someone uses AtlfastKStandardOptions.py).
00089     // In this case, the smearer would overwrite its constructor
00090     // defaults with -9999 and an STL vector of size 0, which will mess up
00091     // the smearing. Therefore if nothing is found, we stop athena running.
00092     //
00093     // I had originally thought it would be enough to just omit calling
00094     // the setSmearParamArray and/or setSmearParamSchema methods if no JOs
00095     // are found, but I decided it is not enough. This is because if, in the future,
00096     // the defaults change (in AtlfastStandardOptions, for example) then someone
00097     // runs using AtlfastKStandardOptions, the code picks up the defaults from the
00098     // constructor in the smearer. Unless someone has maintained the default values
00099     // in the smearer .h file, the defaults used will be the old, wrong ones.
00100     // in short, it is hard to maintain!
00101     //
00102     // The only assumption we make by having smearParamArray and smearParamSchema
00103     // in the jobOptions and failing if they are not fould is that if the defaults change,
00104     // they should be changed in ALL jobOptions.
00105     // Currently, this is:
00106     //  share/Atlfast_CBNT.py
00107     //  share/AtlfastIKinematicDumperStandardOptions.py
00108     //  share/AtlfastKStandardOptions.py
00109     //  share/AtlfastStandardOptions.py
00110     //
00111     //NB: the reason for all this is that the smearer is NOT an algorithm,
00112     //so can not have Gaudi Properties.
00113     //DefaultReconstructedParticleMaker is an algorithm so can have properties.
00114     //Defaults must be set before properties are declared.
00115     //Different particle smearers have different defaults, so we can not set these
00116     //to any sensible values before the properties are loaded. We can only set defaults
00117     //inside the smearer and these are then overridden by the 'set' method to potentially
00118     //give junk physics...
00119     declareProperty( "SmearParamArray", m_smearParamArray );
00120     declareProperty( "SmearParamSchema",m_smearParamSchema );
00121 
00122     // Option to apply efficiencies at particle creation stage
00123     declareProperty( "ApplyEfficiencies", m_applyEfficiencies );
00124 
00125   }
00126   
00127   //--------------------
00128   // Destructor
00129   //--------------------
00130   
00131   DefaultReconstructedParticleMaker::~DefaultReconstructedParticleMaker() {
00132 
00133     m_log << MSG::INFO << "Destructor Called" << endreq;
00134     
00135     if (m_smearer) {
00136       m_log << MSG::INFO << "Deleting smearer" << endreq;
00137       delete m_smearer;
00138     }
00139     if (m_acceptor) {
00140       m_log << MSG::INFO << "Deleting acceptor" << endreq;
00141       delete m_acceptor;
00142     }
00143     if (m_tesIO) {
00144       m_log << MSG::INFO << "Deleting smearer" << endreq;
00145       delete m_tesIO;
00146     }
00147     if (m_ncutter) {
00148       m_log << MSG::INFO << "Deleting smearer" << endreq;
00149       delete m_ncutter;
00150     }
00151 
00152     if (m_lnkReconstructedParticle) delete m_lnkReconstructedParticle;
00153 
00154   }
00155   
00156   
00157   //---------------------------------
00158   // initialise() 
00159   //---------------------------------
00160   
00161   StatusCode DefaultReconstructedParticleMaker::initialize()
00162   {
00163     
00164     // This method is called by Athena once only, after all 
00165     // properties have been set.
00166     
00167     // Set up NCutter to select the required HepMC::GenParticles
00168     typedef HepMC_helper::IMCselector Selector;
00169 
00170     Selector* typeSelector = new HepMC_helper::SelectType( m_particleType);
00171     Selector* kineSelector = new HepMC_helper::MCCuts(m_mcPtMin, m_mcEtaMax);
00172     Selector* fstaSelector = new HepMC_helper::IsFinalState();
00173     Selector* fhscSelector = new HepMC_helper::IsFromHardScatter();
00174 
00175     vector<HepMC_helper::IMCselector*> selectors;
00176     selectors.push_back(fhscSelector);
00177     selectors.push_back(fstaSelector);
00178     selectors.push_back(typeSelector);
00179     selectors.push_back(kineSelector);
00180     
00181     m_ncutter = new HepMC_helper::NCutter(selectors);
00182     
00183     delete typeSelector;
00184     delete kineSelector;
00185     delete fstaSelector;
00186     delete fhscSelector;
00187     //=======================================================
00188     
00189     
00190     
00191 
00192     //get the Global Event Data using singleton pattern
00193     GlobalEventData* ged = GlobalEventData::Instance();
00194     int lumi =       ged->lumi();
00195     int randSeed =   ged->randSeed();
00196 
00197     m_tesIO = new TesIO(ged->mcLocation(), ged->justHardScatter());
00198     
00199     //=====================
00200     if (m_doSmearing){
00201       m_smearer = ISmearerFactory::create( m_particleType,
00202                                            randSeed,
00203                                            lumi,
00204                                            m_muSmearKey,
00205                                            m_muonResFile,
00206                                            m_log,
00207                                            m_smearParamArray,
00208                                            m_smearParamSchema );
00209     } else {
00210       m_smearer = NULL;
00211     }
00212     
00213     //=====================
00214     if (m_applyEfficiencies) this->getAcceptor();
00215     else m_acceptor = NULL;
00216     
00217     HeaderPrinter hp("Atlfast ReconstructedParticle Maker:", m_log);
00218     hp.add("Particle Type           ", m_particleType);
00219     hp.add("Luminosity              ", lumi);        
00220     hp.add("Minimum four-vector Pt  ", m_mcPtMin);
00221     hp.add("Maximum four-vector Eta ", m_mcEtaMax);
00222     hp.add("Minimum particle    Pt  ", m_PtMin);
00223     hp.add("Maximum particle    Eta ", m_EtaMax);
00224     hp.add("Do Smearing             ", m_doSmearing);
00225     hp.add("Muon  Smearing Flag     ", m_muSmearKey);
00226     hp.add("Random Number Seed      ", randSeed);
00227     hp.add("MC location             ", ged->mcLocation());
00228     hp.add("Output Location         ", m_outputLocation);
00229     hp.add("Muon Resolution File    ", m_muonResFile);
00230     hp.print();
00231     
00232     //stop execution if no smearparamschema or smearParamArray are found.
00233     if(m_smearParamArray.size() == 0){
00234       m_log << MSG::WARNING <<"No smearing parameters found in ATLFAST jobOptions..."<< endreq;
00235     }else{
00236       m_log << MSG::INFO  << "Smearing Array m_smearParamArray set to: "<< m_smearParamArray << endreq;
00237     }
00238     if(m_smearParamSchema == -9999){
00239       m_log << MSG::FATAL <<"No smearing schema found in ATLFAST jobOptions..."<< endreq;
00240       return StatusCode::FAILURE;
00241     }else{
00242       m_log << MSG::INFO  << "Smearing Schema m_smearParamSchema set to: "<< m_smearParamSchema << endreq;
00243     }
00244     
00245     return StatusCode::SUCCESS;
00246   }
00247   
00248   //---------------------------------
00249   // finalise() 
00250   //---------------------------------
00251   
00252   StatusCode DefaultReconstructedParticleMaker::finalize()
00253   {
00254     
00255     m_log << MSG::INFO << "Finalizing" << endreq;  
00256     return StatusCode::SUCCESS ;
00257   }
00258   
00259   
00260   //----------------------------------------------
00261   // execute() method called once per event
00262   //----------------------------------------------
00263   //
00264   //  This algorithm creates smeared ReconstructedParticles.
00265   // 
00266   //  It takes HepMC::GenParticles from the TES as input. 
00267   //  Only HepMC::GenParticles satisfying the selection requirements
00268   //  are used.
00269   //
00270   //  A candidate ReconstructedParticle object is made by smearing the 
00271   //  four vector of the HepMC::GenParticle. 
00272   // 
00273   //  It then applies kinematic selection criteria to the properties of the 
00274   //  ReconstructedParticle. Only those which pass the cuts are kept.
00275   //
00276   //  Finally, all surviving ReconstructedParticles are added to the event 
00277   //  store.
00278   //
00279   //
00280   
00281   StatusCode DefaultReconstructedParticleMaker::execute( )
00282   {
00283     
00284     std::string mess;
00285     m_log << MSG::DEBUG << "Execute() " << endreq;
00286     
00287 
00288     //.............................
00289     // Obtain the truth HepMC::GenParticles which we want to process.
00290     // We fill a local collection with pointers to these Particles.
00291     // The private method which is used applies selection criteria
00292     // to the HepMC::GenParticles before placing them in the collection
00293     
00294     MCparticleCollection  my_MC_particles ;
00295     MCparticleCollectionCIter src ;
00296     
00297     TesIoStat stat = m_tesIO->getMC( my_MC_particles, m_ncutter ) ;
00298     mess = stat? "Retrieved MC from TES ":"Failed MC retrieve from TES";
00299     m_log << MSG::DEBUG << mess << endreq;
00300     
00301     // ......................
00302     // Make a container object which will store pointers to all  
00303     // ReconstructedParticles which are successfully created.  
00304     // Since it is going into the TES, it has to be a special Athena type 
00305     // of container. This is defined in an include file.
00306     
00307     ReconstructedParticleCollection* myReconstructedParticles 
00308       = new ReconstructedParticleCollection ;
00309     
00310     
00311     //.........................................................
00312     // From each mc truth Particle, create a ReconstructedParticle candidate.
00313     // If it satisfies requirements add to the output collection
00314     
00315     ReconstructedParticle* candidate ;
00316 
00317     // Booleans for overall accept decision and kinematic and 
00318     // pre-defined efficiency accept decisions separately
00319     bool accept = true, accept_kinematic = true, accept_efficiency = true;
00320     
00321     for(src = my_MC_particles.begin() ; src != my_MC_particles.end() ; ++src){ 
00322       
00323       candidate = this->create( *src ); 
00324       
00325       // Accept decision based on pre-defined efficiency function
00326       if (m_applyEfficiencies){ 
00327         bool instance_check = m_acceptor ? true : false;
00328         m_log << MSG::DEBUG << "Does m_acceptor point to anything sensible?: " << instance_check << endreq;
00329         accept_efficiency = ( m_acceptor && m_acceptor->accept( *candidate, m_log ) ) ? true : false;
00330         m_log << MSG::DEBUG << "m_acceptor && m_acceptor->accept( *candidate ) = " 
00331             << accept_efficiency << endreq;
00332       }
00333       // Accept decision based on kinematic cuts
00334       accept_kinematic = this->isAcceptable( candidate );
00335       
00336       accept = m_applyEfficiencies ? 
00337         accept_efficiency && accept_kinematic : 
00338         accept_kinematic;
00339       
00340       if ( accept ) {
00341         m_log << MSG::DEBUG << "Accepted" << endreq;
00342         myReconstructedParticles->push_back( candidate );     
00343       }else{
00344         m_log << MSG::DEBUG << "Rejected" << endreq;
00345         delete candidate;
00346       }
00347       
00348     }
00349     
00350     
00351     //.....................................
00352     // Sort into ascending order of pT
00353     
00354     if( myReconstructedParticles->size() > 0 ){
00355       sort( myReconstructedParticles->begin(),
00356             myReconstructedParticles->end(),
00357             SortAttribute::DescendingPT()
00358             ) ;
00359     }
00360     
00361     
00362     //......................................
00363     // Deal with resulting ReconstructedParticles (if any)
00364     
00365     stat =m_tesIO->store( myReconstructedParticles, m_outputLocation );
00366     mess = stat? "Store to TES success":"Store to TES failure";    
00367     m_log << MSG::DEBUG << mess << endreq;
00368 
00369     m_log << MSG::DEBUG << "Ending<-------- " << endreq;
00370     
00371     StatusCode sc=StatusCode::SUCCESS;  
00372     return sc ;
00373     
00374   }
00375   
00376   
00377   
00378   //----------------------------------
00379   // create()
00380   //----------------------------------
00381   
00382   // Takes a single MC Particle and creates a reconstructed
00383   // ReconstructedParticle according to the desired criteria
00384   //
00385   // Note that we must NEW these particles so they can go to the TES
00386   // and if we decide that we do not want them, we must DELETE them
00387   // Once they are put to the TES, they are no longer our responsibility to 
00388   // delete
00389   
00390   ReconstructedParticle* 
00391   DefaultReconstructedParticleMaker::create ( const HepMC::GenParticle* src ){
00392     
00393     HepLorentzVector evec;
00394     
00395     if (m_doSmearing) {
00396       
00397       // Ask our Smearer make a smeared 4-vector
00398       evec = m_smearer->smear( *src );
00399       
00400       m_log << MSG::DEBUG 
00401           << "\n\t"
00402           << "Unsmeared four-vector: " 
00403           << src->momentum()
00404           << "\n\t" 
00405           << "Smeared four-vector  : " 
00406           << evec 
00407           << endreq;
00408       
00409     }else{
00410       
00411       evec = src->momentum();
00412       
00413     }
00414     
00415     ReconstructedParticle* candidate = 
00416       new ReconstructedParticle( src->pdg_id(), evec, src );
00417     
00418     m_log << MSG::DEBUG 
00419           << "Created ReconstructedParticle: \n\t " 
00420           << candidate 
00421           << endreq;
00422     
00423     return candidate ;
00424     
00425   }
00426   
00427   
00428   //-------------------------------------------
00429   // isAcceptable
00430   //------------------------------------------
00431   
00432   // Decides whether a candidate is acceptable to this Maker, i.e. whether
00433   // it wants to proceed and add it to its output product collection
00434   
00435   bool DefaultReconstructedParticleMaker::isAcceptable 
00436   (const ReconstructedParticle* candidate ){
00437     
00438     // Apply kinematic criteria to the candidate DefaultReconstructedParticle
00439     
00440     if( candidate->pT() < m_PtMin ) {        
00441       m_log << MSG::DEBUG 
00442           << "Candidate failed pt cut: pt was " 
00443           << candidate->pT() 
00444           << " cut was " 
00445           << m_PtMin 
00446           << endreq;
00447       return false ;
00448     }
00449     
00450     if( abs(candidate->eta()) > m_EtaMax ) {
00451       m_log << MSG::DEBUG 
00452           << "Candidate failed max eta cut: eta was " 
00453           << candidate->eta() 
00454           << " cut was " 
00455           << m_EtaMax 
00456           << endreq;
00457       return false ;
00458     }
00459     
00460     m_log << MSG::DEBUG 
00461         << "Candidate passed selection cuts "
00462         << endreq ;
00463     
00464     return true ;
00465   }
00466   
00467   //-------------------------------------------
00468   // getAcceptor
00469   //------------------------------------------
00470   void DefaultReconstructedParticleMaker::getAcceptor(){
00471 
00472     m_log << MSG::DEBUG << "Getting an acceptor" << endreq;
00473 
00474     if (m_particleType == 13){
00475       m_acceptor = new MuonAcceptor(m_muSmearKey,m_log);
00476     }else{
00477       m_log << MSG::ERROR << "No Acceptor exists for this particle type!" << endreq;
00478       m_acceptor = NULL;
00479     }
00480 
00481   }
00482   
00483 } // end namespace bracket
00484 
00485 

Generated on Mon Sep 24 14:19:12 2007 for AtlfastAlgs by  doxygen 1.5.1