KIsolator.cxx

Go to the documentation of this file.
00001 // ================================================
00002 // KIsolator class Implementation
00003 // ================================================
00004 //
00005 // THIS TEXT TO BE REPLACED BY ATLAS STANDARD FORMAT
00006 //
00007 // Namespace ATLFast
00008 //
00009 
00010 #include "AtlfastAlgs/KIsolator.h"
00011 //#include "AtlfastAlgs/ClusterIsAssoc.h"
00012 #include "AtlfastUtils/IsAssociated.h"
00013 #include "AtlfastAlgs/GlobalEventData.h"
00014 
00015 #include "AtlfastEvent/Phi.h"
00016 #include "AtlfastEvent/ICluster.h"
00017 
00018 #include "AtlfastUtils/FunctionObjects.h"
00019 #include "AtlfastUtils/HeaderPrinter.h"
00020 #include "AtlfastUtils/HepMC_helper/IMCselector.h"
00021 
00022 #include <cmath> 
00023 #include <algorithm>
00024 #include <assert.h>
00025 
00026 // Gaudi includes
00027 #include "GaudiKernel/DataSvc.h"
00028 #include "AtlfastEvent/MsgStreamDefs.h"
00029 
00030 #include "CLHEP/Units/SystemOfUnits.h"
00031 
00032 namespace Atlfast {
00033   using std::partial_sort;
00034 
00035 
00036   //--------------------------------
00037   // Constructors and destructors
00038   //--------------------------------
00039   
00040   KIsolator::KIsolator 
00041   ( const std::string& name, ISvcLocator* pSvcLocator ) 
00042     : Algorithm( name, pSvcLocator ),
00043       m_tesIO(0) {
00044     
00045     // Setting the parameter defaults.
00046     m_rClusterMatch      = 0.150;
00047     m_rClusterIsolation  = 0.400;
00048     m_eClusterIsolation  = 0.0*GeV;
00049     m_rCellIsolation     = 0.200;
00050     m_eCellIsolation     = 10.0*GeV;
00051     
00052     // Default paths for entities in the TES
00053     m_inputLocation                 = "/Event/AtlfastElectrons";
00054     m_cellLocation                  = "/Event/AtlfastCells";
00055     m_clusterLocation               = "/Event/AtlfastClusters";
00056     m_isolatedOutputLocation        = "/Event/AtlfastIsolatedElectrons";
00057     m_nonIsolatedOutputLocation     = "/Event/AtlfastNonIsolatedElectrons";
00058     
00059     // This is how you declare the paramemters to Gaudi so that
00060     // they can be over-written via the job options file
00061     
00062     declareProperty( "RClusterMatch",             m_rClusterMatch ) ;
00063     declareProperty( "RClusterIsolation",         m_rClusterIsolation ) ;
00064     declareProperty( "EClusterIsolation",         m_eClusterIsolation ) ;
00065     declareProperty( "RCellIsolation",            m_rCellIsolation ) ;
00066     declareProperty( "ECellIsolation",            m_eCellIsolation ) ;
00067     
00068     declareProperty( "InputLocation",             m_inputLocation ) ;
00069     declareProperty( "CellLocation",              m_cellLocation ) ;
00070     declareProperty( "ClusterLocation",           m_clusterLocation ) ;
00071     declareProperty( "IsolatedOutputLocation",    m_isolatedOutputLocation ) ;
00072     declareProperty( "NonIsolatedOutputLocation", m_nonIsolatedOutputLocation ) ;
00073     
00074   }
00075   
00076   // Destructor
00077   KIsolator::~KIsolator() {
00078     MsgStream log( messageService(), name() ) ;
00079     log << MSG::INFO << "destructor" << endreq;
00080     if (m_tesIO) delete m_tesIO;
00081   } 
00082   
00083   
00084   //---------------------------------
00085   // initialise() 
00086   //---------------------------------
00087   
00088   StatusCode KIsolator::initialize(){
00089     MsgStream log( messageService(), name() ) ;
00090     log << MSG::DEBUG << "Initialising" << endreq;
00091     
00092     
00093     //get the Global Event Data using singleton pattern
00094     GlobalEventData* ged = GlobalEventData::Instance();
00095     m_visibleToCal   = ged -> visibleToCal();
00096     m_mcLocation     = ged -> mcLocation();
00097     //    m_tesIO = new TesIO(eventDataService());
00098     m_tesIO = new TesIO(m_mcLocation, ged->justHardScatter());
00099 
00100 
00101     HeaderPrinter hp("Atlfast KIsolator:", log);
00102     
00103     hp.add("TES Locations:             ");
00104     hp.add(" Particles from            ", m_inputLocation); 
00105     hp.add(" Cells from                ", m_cellLocation);    
00106     hp.add(" Clusters from             ", m_clusterLocation); 
00107     hp.add(" Isolated Particles to     ", m_isolatedOutputLocation);
00108     hp.add(" Non-Isolated Particles to ", m_nonIsolatedOutputLocation);
00109     hp.add("Cluster match DeltaR       ", m_rClusterMatch);
00110     hp.add("Cluster isolation DeltaR   ", m_rClusterIsolation);
00111     hp.add("Cluster isolation E thresh ", m_eClusterIsolation);
00112     hp.add("Cell isolation DeltaR      ", m_rCellIsolation);
00113     hp.add("Cell isolation E thresh    ", m_eCellIsolation);
00114     hp.print();
00115     
00116     
00117     return StatusCode::SUCCESS ;
00118   }
00119   
00120   //---------------------------------
00121   // finalise() 
00122   //---------------------------------
00123   
00124   StatusCode KIsolator::finalize(){
00125     MsgStream log( messageService(), name() ) ;
00126     log << MSG::INFO << "finalizing" << endreq;
00127     return StatusCode::SUCCESS ;
00128   }
00129   
00130   
00131   //----------------------------------------------
00132   // execute() method called once per event
00133   //----------------------------------------------
00134   //
00135   //  This algorithm creates isolated electrons. 
00136   //  It scans the list of MC electrons. If an electron is found it creates 
00137   //  a candidate Electron object with a smeared energy.  Different 
00138   //  energy-smearing for low luminosity and high luminosity can be invoked.
00139   //  It then checks several isolation criteria with respect to calorimeter
00140   //  clusters and cells.
00141   //  Only if the isolation is satisfied is the Electron kept.
00142   //  Finally all successful ELectrons are added to the event store.
00143   
00144   
00145   StatusCode KIsolator::execute( ){
00146     
00147     //................................
00148     // make a message logging stream
00149     
00150     MsgStream log( messageService(), name() ) ;
00151     std::string mess;
00152     //...............................
00153     // Extract the input particles which are to be tested for isolation.
00154     
00155     //std::vector<ReconstructedParticle*> particles;
00156     const ReconstructedParticleCollection* particles(0);
00157     if(!m_tesIO->getDH(particles, m_inputLocation)){
00158       log << MSG::DEBUG 
00159           << "No reconstructed particles in TES to treat" 
00160           << endreq ;
00161       return StatusCode::SUCCESS ;
00162     }
00163     
00164     log << MSG::DEBUG 
00165         << "Found " 
00166         << particles->size() 
00167         << " particles in TES "
00168         << endreq ;
00169     
00170     
00171     //.........................................................
00172     // Extract the (pointers to) cells and clusters from the TES into 
00173     // locally defined arrays.
00174     
00175     
00176     std::vector<ITwoCptCell*> cells;
00177     if(!m_tesIO->copy<ITwoCptCellCollection> (cells, m_cellLocation)){
00178       
00179       log << MSG::DEBUG 
00180           << "No Cells found in TES at " 
00181           << m_cellLocation 
00182           << endreq ;
00183     }
00184     
00185     
00186     std::vector<ICluster*> clusters;
00187     if(!m_tesIO->copy<IClusterCollection>(clusters, m_clusterLocation)){
00188       log << MSG::DEBUG 
00189           << "No Clusters found in TES at " 
00190           << m_clusterLocation 
00191           << endreq ;
00192     }
00193     
00194     
00195     // ......................
00196     // Make an empty container object which will store (pointers to) all 
00197     // sucessfully isolated and non isolated electrons.  
00198     
00199     ReconstructedParticleCollection* isolatedParticles = 
00200       new ReconstructedParticleCollection ;
00201     
00202     ReconstructedParticleCollection* nonIsolatedParticles = 
00203       new ReconstructedParticleCollection ;
00204     
00205     
00206     //.........................................................
00207     // For each particle in the input list test if it is isolated.
00208     // If so copy it into the output collection.
00209     
00210     ReconstructedParticleCollection::const_iterator particle ;
00211     
00212     for( particle = particles->begin(); 
00213          particle != particles->end(); 
00214          ++particle)
00215       {       
00216         if( this->isIsolated( log, particle, cells, clusters ) )     
00217           isolatedParticles->push_back
00218             ( new ReconstructedParticle( *particle ) ); 
00219         else
00220           nonIsolatedParticles->push_back
00221             ( new ReconstructedParticle( *particle ) );         
00222       }
00223     
00224     
00225     //......................................
00226     // Register particles in the transient event store. 
00227     
00228     TesIoStat tis;
00229     tis = m_tesIO->store(isolatedParticles, m_isolatedOutputLocation );  
00230     if( tis.isNotValid() ) {
00231       log << MSG::ERROR << "Failed to register output in TES at " 
00232           << m_isolatedOutputLocation <<  endreq ;
00233       return tis;
00234     } else{
00235       log << MSG::DEBUG << "Written " << isolatedParticles->size() 
00236           << " isolated particles to TES " << endreq;
00237     }
00238     
00239     tis = m_tesIO->store(nonIsolatedParticles, m_nonIsolatedOutputLocation );
00240     if( tis.isNotValid() ) {
00241       log << MSG::ERROR << "Failed to register output in TES at " 
00242           << m_nonIsolatedOutputLocation <<  endreq ;
00243     } else {
00244       log << MSG::DEBUG << "Written " << nonIsolatedParticles->size() 
00245           << " NON-isolated particles to TES " << endreq;
00246     }
00247     
00248     return tis;
00249     
00250   }
00251 
00252 
00253   //-------------------------------------------
00254   // private: response (gap effect)
00255   //------------------------------------------
00256   double KIsolator::gapResponse(double eta){
00257     double aEta = std::abs(eta);
00258     double p1 = 1.1095;
00259     double p2 = -7.494*std::pow((aEta - p1),2);
00260     double p3 = -25.275*std::pow((aEta - p1),2);
00261     double p4 = 14.52;
00262     return ((aEta>1.3)&&(aEta<1.9))? 
00263       1.0 - std::exp(p2 - p4*std::exp(p3)) : 1.0;
00264   }
00265   
00266   
00267   //-------------------------------------------
00268   // private: isIsolated
00269   //------------------------------------------
00270   
00271   // Checks whether a candidate electron is isolated from clusters
00272   // and cells
00273   
00274   bool KIsolator::isIsolated
00275   ( MsgStream& log, 
00276     ReconstructedParticleCollection::const_iterator particle,
00277     std::vector<ITwoCptCell*>& storedCells,
00278     std::vector<ICluster*>& storedClusters
00279     
00280     ){
00281     
00282     log << MSG::DEBUG << "\n\t Treating particle: " << *particle ;
00283     
00284     // Things we need to remember until the end of the method
00285     // If, during processing of Clusters, we identify an "associated cluster"
00286     // we remember it for use if the particle is finally judged to be isolated
00287     bool associated = false ;
00288     ICluster* associatedCluster = NULL ;
00289     
00290     
00291     
00292     //....................................
00293     // Cluster isolation
00294     
00295       
00296     if( !storedClusters.empty() ) {
00297       
00298       // Make a local copy as we want to mutate the list of pointers
00299       std::vector<ICluster*>  clusters( 
00300                                       storedClusters.begin(), 
00301                                       storedClusters.end() 
00302                                       );
00303       
00304       // My own test: would be removed
00305       std::vector<ICluster*>::iterator it;
00306       for (it=clusters.begin(); it!=clusters.end(); ++it) {
00307         double dR = m_kinehelp.deltaR(*particle,*it);
00308         if (dR>m_rClusterMatch) continue;
00309         log << "\n\t -->  cluster: " << *it ;
00310         log << "\n\t -->   DeltaR: " << dR;
00311         log << "\n\t -->  EtC-EtP: " 
00312             << (*it)->eT() - 
00313           (*particle)->eT()*gapResponse((*particle)->eta());
00314         log << "\n\t ---------------------------------------- " <<endreq;
00315       }
00316       
00317       
00318       //Only use clusters not already claimed by ReconstructedParticles
00319       std::vector<ICluster*>::iterator firstNonAssociatedCluster ;
00320       firstNonAssociatedCluster = 
00321         std::partition(
00322                        clusters.begin(),
00323                        clusters.end(),
00324                        IsAssociated<ReconstructedParticle>
00325                        );
00326       if(firstNonAssociatedCluster != clusters.begin()){
00327         log<<MSG::DEBUG<<"First "
00328            <<firstNonAssociatedCluster-clusters.begin()
00329            <<" clusters are associated to ReconstructedParticles "
00330            <<clusters.end()-firstNonAssociatedCluster
00331            <<" cluster(s) remain"
00332            <<endreq;
00333       }else{
00334         log<<MSG::DEBUG
00335            <<"No clusters are associated to ReconstructedParticles"
00336            <<endreq;
00337       }
00338       if(clusters.end()!=firstNonAssociatedCluster){
00339         // .....................
00340         // Associate unclaimed clusters with current particle. 
00341         // This looks at the nearest cluster only, and decides whether
00342         // it is within an "association" cone
00343         
00344         partial_sort(
00345                      firstNonAssociatedCluster,
00346                      firstNonAssociatedCluster+1,
00347                      clusters.end(), 
00348                      SortAttribute::DeltaR( *particle )
00349                      );
00350         
00351         log<<MSG::DEBUG<<"Sorted clusters "<<endreq;
00352         
00353         associated =
00354           (m_kinehelp.deltaR(*particle, *firstNonAssociatedCluster) <  
00355            m_rClusterMatch);
00356         
00357         if( associated ) 
00358           {
00359             log << "\n\t -->Found associated cluster: "  
00360                 << *clusters.begin() ;
00361             
00362             // Remember the relevant cluster until the end of this method
00363             associatedCluster = *firstNonAssociatedCluster ;
00364             
00365             // Set the first nonassociated cluster
00366             ++firstNonAssociatedCluster;
00367             
00368           }
00369         
00370         
00371         //............................................
00372         // Now we can check Cluster Isolation 
00373         // (if there is at least one more cluster to check)
00374         
00375         // Use kinematic helper to do all work
00376         double eClusterSum = m_kinehelp.sumETInCone( 
00377                                                     firstNonAssociatedCluster, 
00378                                                     clusters.end(), 
00379                                                     *particle,
00380                                                     m_rClusterIsolation
00381                                                     );
00382         
00383         // Apply the cut criteria
00384         
00385         if( eClusterSum  > m_eClusterIsolation ) 
00386           log  << "\n\t -->Excess Cluster energy in cone = " << eClusterSum 
00387                << "   => NOT-ISOLATED " << endreq;       
00388         else
00389           log  << "\n\t -->Excess Cluster energy in cone = " << eClusterSum 
00390                << "   => ISOLATED "  ;
00391         
00392         if( eClusterSum  > m_eClusterIsolation )  return false ;
00393         
00394       }
00395       
00396     }
00397     
00398     //............................................
00399     // Cell Isolation: 
00400     
00401     if( !storedCells.empty() ) {
00402       
00403       // Test on isolation in respect of the total transverese energy of all 
00404       // Cells within a given r-cone
00405 
00406 
00407       // dummy ReconstructedParticle to heve simple access to
00408       // unsmeared 4-vector to do isolation
00409       ReconstructedParticle* rp = 
00410         new ReconstructedParticle(
00411                                   (*particle)->pdg_id(),
00412                                   (*particle)->momentum(),
00413                                   (*particle)->truth()
00414                                   );
00415 
00416 
00417       // Use kinematic helper to do all work
00418       double eCoreSum = m_kinehelp.sumETInCone(
00419                                                storedCells.begin(), 
00420                                                storedCells.end(), 
00421                                                rp,
00422                                                m_rCellIsolation
00423                                                );
00424       
00425 
00426       // delete the dummy ReconstructedParticle
00427       delete rp;
00428 
00429 
00430       // Subtract the energy associated with particle under test
00431       // as the cells summed will have included its deposit
00432       //    CalSelect depositsInCal;
00433       //    if(depositsInCal( *particle) ) eCellSum -= (*particle)->eT() ;
00434       bool itDeposits = m_visibleToCal->operator()( (*particle)->truth() );
00435 
00436 
00437       // consider the effect of transition region (from FastShower)
00438       log << "\n\t -->Applying gap correction factor: "
00439           << gapResponse((*particle)->eta()) << endreq ; 
00440 
00441       double eCoreIsolation = eCoreSum;
00442       if(itDeposits) eCoreIsolation -=  
00443                        ((*particle)->eT())*gapResponse((*particle)->eta());
00444       
00445       
00446       // Apply isolation criteria
00447       
00448       if( eCoreIsolation  > m_eCellIsolation ) 
00449         log  
00450           << "\n\t -->Excess energy in core (R<0.2) = " << eCoreIsolation 
00451           << "   => NOT-ISOLATED " << endreq ;    
00452       else
00453         log   
00454           << "\n\t -->Excess energy in core (R<0.2) = " << eCoreIsolation
00455           << "   => ISOLATED " << endreq ;
00456                   
00457       if( eCoreIsolation  > m_eCellIsolation )return false;
00458       
00459     }
00460     
00461     //..........................................
00462     // If we get here then the candidate was judged to be isolated
00463     
00464     // It is only now that we wish to set associations between isolated
00465     // particles and clusters. I.e we dont want to flag associations for 
00466     // non-isolated particles
00467     
00468     if( associated ) {
00469       
00470       // Set the association from Particle -> Cluster
00471       IAOO* iamp = *particle;
00472       iamp->associate( associatedCluster ) ;
00473 
00474       log  << MSG::DEBUG 
00475            << "Particle of type "<< (*particle)->pdg_id()<<" associated to Cluster" 
00476            << endreq;
00477       //assert(IsAssociated<Cluster>( *particle ));
00478 
00479       // Set the association from Cluster -> Particle
00480       IAOO* iamc = associatedCluster;
00481       iamc->associate( *particle ) ;
00482 
00483       log  << MSG::DEBUG 
00484            << "Cluster associated to Particle of type "<< (*particle)->pdg_id() 
00485            << endreq;
00486       
00487       //assert(IsAssociated<ReconstructedParticle>( associatedCluster ));
00488     }
00489     
00490     log << endreq ;
00491     
00492     return true ;
00493   }
00494   
00495 } // end of namespace bracket

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