Report problems to ATLAS LXR Team (with time and IP address indicated)

The LXR Cross Referencer

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Architecture: linux ]
Version: head ] [ nightly ] [ GaudiDev ]
  Links to LXR source navigation pages for stable releases [ 12.*.* ]   [ 13.*.* ]   [ 14.*.* ]   [ 15.*.* ] 

001 // ================================================
002 // Isolator class Implementation
003 // ================================================
004 //
005 // THIS TEXT TO BE REPLACED BY ATLAS STANDARD FORMAT
006 //
007 // Namespace ATLFast
008 //
009 
010 #include "AtlfastAlgs/Isolator.h"
011 #include "AtlfastAlgs/JetSmearer.h"
012 #include "AtlfastAlgs/GlobalEventData.h"
013 
014 #include "AtlfastEvent/Phi.h"
015 #include "AtlfastEvent/ICluster.h"
016 
017 #include "AtlfastUtils/IsAssociated.h"
018 #include "AtlfastUtils/FunctionObjects.h"
019 #include "AtlfastUtils/HeaderPrinter.h"
020 #include "TruthHelper/GenIMCselector.h"
021 
022 #include <cmath> 
023 #include <algorithm>
024 #include <assert.h>
025 
026 // Gaudi includes
027 #include "GaudiKernel/DataSvc.h"
028 #include "AtlfastEvent/MsgStreamDefs.h"
029 
030 #include "CLHEP/Units/SystemOfUnits.h"
031 
032 
033 namespace Atlfast {
034   using std::partial_sort;
035 
036 /**
037    * @brief Associates ReconstructedParticles to Clusters and evaluates isolation.
038    *
039    * The associations are established by searching in a user-defined cone around
040    * the RP position for unassociated Clusters.<br>
041    * The isolation is calculated by searching in user-defined cones around the
042    * RP position for Clusters and unused (unclustered) Cells. The corresponding
043    * energies are then compared to user-defined limits.
044    *
045    * @image html Isolator.jpg "Isolator sequence"
046    */
047 
048   //--------------------------------
049   // Constructors and destructors
050   //--------------------------------
051   
052   Isolator::Isolator 
053   ( const std::string& name, ISvcLocator* pSvcLocator ) 
054     : Algorithm( name, pSvcLocator ),
055       m_cellSmearer( 0 ),
056       m_tesIO( 0 ) {
057     
058     // Setting the parameter defaults.
059     /** R-cone for associating a Cluster to a particle */
060     m_rClusterMatch      = 0.150;
061     /** R-cone in which to sum unassociated Cluster eT */
062     m_rClusterIsolation  = 0.400;
063     /** eT threshold to apply to summed Cluster eT */
064     m_eClusterIsolation  = 0.0*GeV;
065     /** R-cone in which to sum Cell eT */
066     m_rCellIsolation     = 0.200;
067     /** eT threshold to apply to excess summed Cluster eT */
068     m_eCellIsolation     = 10.0*GeV;
069     
070     /** Upper and lower bounds of halo interval in dR */
071     m_rLowerHalo         = 0.2;
072     m_rHigherHalo        = 0.4;
073     
074      /** Whether or not to smear cells in isolation ET sum */
075     m_smearCells         = false;
076 
077     m_fastShower         = false;
078 
079     // Default paths for entities in the TES
080 
081     /** Location in TES to obtain input particles to be isolated */
082     m_inputLocation                 = "/Event/AtlfastElectrons";
083     m_cellLocation                  = "/Event/AtlfastCells";
084     m_clusterLocation               = "/Event/AtlfastClusters";
085     m_isolatedOutputLocation        = "/Event/AtlfastIsolatedElectrons";
086     m_nonIsolatedOutputLocation     = "/Event/AtlfastNonIsolatedElectrons";
087     
088     // This is how you declare the paramemters to Gaudi so that
089     // they can be over-written via the job options file
090     
091     declareProperty( "RClusterMatch",             m_rClusterMatch ) ;
092     declareProperty( "RClusterIsolation",         m_rClusterIsolation ) ;
093     declareProperty( "EClusterIsolation",         m_eClusterIsolation ) ;
094     declareProperty( "RCellIsolation",            m_rCellIsolation ) ;
095     declareProperty( "ECellIsolation",            m_eCellIsolation ) ;
096     
097     declareProperty( "InputLocation",             m_inputLocation ) ;
098     declareProperty( "CellLocation",              m_cellLocation ) ;
099     declareProperty( "ClusterLocation",           m_clusterLocation ) ;
100     declareProperty( "IsolatedOutputLocation",    m_isolatedOutputLocation ) ;
101     declareProperty( "NonIsolatedOutputLocation", m_nonIsolatedOutputLocation ) ;
102     
103     declareProperty( "RLowerHalo",                m_rLowerHalo ) ;
104     declareProperty( "RHigherHalo",               m_rHigherHalo ) ;
105 
106     declareProperty( "SmearCells",                m_smearCells ) ;
107     declareProperty( "FastShower",                m_fastShower ) ;
108   }
109   
110   // Destructor
111   Isolator::~Isolator() {
112     MsgStream log( messageService(), name() ) ;
113     log << MSG::INFO << "destructor" << endreq;
114     if (m_cellSmearer) {
115       log << MSG::INFO << "Deleting Cell Smearer" << endreq;
116       delete m_cellSmearer;
117     }
118     if (m_tesIO) {
119       delete m_tesIO;
120     }
121   } 
122   
123   
124   //---------------------------------
125   // initialise() 
126   //---------------------------------
127   
128   StatusCode Isolator::initialize(){
129     MsgStream log( messageService(), name() ) ;
130     log << MSG::DEBUG << "Initialising" << endreq;
131     
132     
133     //get the Global Event Data using singleton pattern
134     GlobalEventData* ged     = GlobalEventData::Instance();
135     m_visibleToCal           = ged -> visibleToCal();
136     m_mcLocation             = ged -> mcLocation();
137     int randSeed             = ged->randSeed() ;
138     int lumi                 = ged -> lumi();
139     double barrelForwardEta  = ged -> barrelForwardEta();
140 
141     m_tesIO = new TesIO(m_mcLocation, ged->justHardScatter());
142 
143     if ( m_smearCells ){
144       m_cellSmearer             = new JetSmearer(randSeed, 
145                                                  lumi,
146                                                  0., 
147                                                  0., 
148                                                  barrelForwardEta);    
149     } else {
150       m_cellSmearer = 0;
151     }
152     
153     HeaderPrinter hp("Atlfast Isolator:", log);
154     
155     hp.add("TES Locations:             ");
156     hp.add(" Particles from            ", m_inputLocation); 
157     hp.add(" Cells from                ", m_cellLocation);    
158     hp.add(" Clusters from             ", m_clusterLocation); 
159     hp.add(" Isolated Particles to     ", m_isolatedOutputLocation);
160     hp.add(" Non-Isolated Particles to ", m_nonIsolatedOutputLocation);
161     hp.add("Cluster match DeltaR       ", m_rClusterMatch);
162     hp.add("Cluster isolation DeltaR   ", m_rClusterIsolation);
163     hp.add("Cluster isolation E thresh ", m_eClusterIsolation);
164     hp.add("Cell isolation DeltaR      ", m_rCellIsolation);
165     hp.add("Cell isolation E thresh    ", m_eCellIsolation);
166     hp.add("Smear Cells in isolation?  ", m_smearCells);
167     hp.add("Running FastShower         ", m_fastShower);
168     hp.print();
169     
170     
171     return StatusCode::SUCCESS ;
172   }
173   
174   //---------------------------------
175   // finalise() 
176   //---------------------------------
177   
178   StatusCode Isolator::finalize(){
179     MsgStream log( messageService(), name() ) ;
180     log << MSG::INFO << "finalizing" << endreq;
181     return StatusCode::SUCCESS ;
182   }
183   
184   
185   //----------------------------------------------
186   // execute() method called once per event
187   //----------------------------------------------
188   //
189   //  This algorithm creates isolated reconstructed particles (electron, photon or muon) 
190   //  It scans the list of MC reconstructed particles. If a particle is found it creates 
191   //  a candidate particle object with a smeared energy.  Different 
192   //  energy-smearing for low luminosity and high luminosity can be invoked.
193   //  It then checks several isolation criteria with respect to calorimeter
194   //  clusters and cells.
195   //  Only if the isolation is satisfied is the reconstructed particle kept.
196   //  Finally all successful reconstructed particles are added to the event store.
197   
198   
199   StatusCode Isolator::execute( ){
200     
201     //................................
202     // make a message logging stream
203     
204     MsgStream log( messageService(), name() ) ;
205     std::string mess;
206     //...............................
207     // Extract the input particles which are to be tested for isolation.
208     
209     //std::vector<ReconstructedParticle*> particles;
210     const ReconstructedParticleCollection* particles(0);
211     if(!m_tesIO->getDH(particles, m_inputLocation)){
212       log << MSG::DEBUG 
213           << "No reconstructed particles in TES to treat" 
214           << endreq ;
215       return StatusCode::SUCCESS ;
216     }
217     
218     log << MSG::DEBUG 
219         << "Found " 
220         << particles->size() 
221         << " particles in TES "
222         << endreq ;
223     
224     
225     //.........................................................
226     // Extract the (pointers to) cells and clusters from the TES into 
227     // locally defined arrays.
228     
229     
230     std::vector<ITwoCptCell*> cells;
231     if(!m_tesIO->copy<ITwoCptCellCollection> (cells, m_cellLocation)){
232       
233       log << MSG::DEBUG 
234           << "No Cells found in TES at " 
235           << m_cellLocation 
236           << endreq ;
237     }
238     
239     
240     std::vector<ICluster*> clusters;
241     if(!m_tesIO->copy<IClusterCollection>(clusters, m_clusterLocation)){
242       log << MSG::DEBUG 
243           << "No Clusters found in TES at " 
244           << m_clusterLocation 
245           << endreq ;
246     }
247     
248     
249     // ......................
250     // Make an empty container object which will store (pointers to) all 
251     // sucessfully isolated and non isolated particles.  
252     
253     ReconstructedParticleCollection* isolatedParticles = 
254       new ReconstructedParticleCollection ;
255     
256     ReconstructedParticleCollection* nonIsolatedParticles = 
257       new ReconstructedParticleCollection ;
258     
259     
260     //.........................................................
261     // For each particle in the input list test if it is isolated.
262     // If so copy it into the output collection.
263     
264     ReconstructedParticleCollection::const_iterator particle ;
265     
266     for( particle = particles->begin(); 
267          particle != particles->end(); 
268          ++particle)
269       {       
270         if( this->isIsolated( log, particle, cells, clusters ) )     
271           isolatedParticles->push_back
272             ( new ReconstructedParticle( *particle ) ); 
273         else
274           nonIsolatedParticles->push_back
275             ( new ReconstructedParticle( *particle ) );         
276       }
277     
278     
279     //......................................
280     // Register particles in the transient event store. 
281     
282     TesIoStat tis;
283     tis = m_tesIO->store(isolatedParticles, m_isolatedOutputLocation );  
284     if( tis.isNotValid() ) {
285       log << MSG::ERROR << "Failed to register output in TES at " 
286           << m_isolatedOutputLocation <<  endreq ;
287       return tis;
288     } else{
289       log << MSG::DEBUG << "Written " << isolatedParticles->size() 
290           << " isolated particles to TES " << endreq;
291     }
292     
293     tis = m_tesIO->store(nonIsolatedParticles, m_nonIsolatedOutputLocation );
294     if( tis.isNotValid() ) {
295       log << MSG::ERROR << "Failed to register output in TES at " 
296           << m_nonIsolatedOutputLocation <<  endreq ;
297     } else {
298       log << MSG::DEBUG << "Written " << nonIsolatedParticles->size() 
299           << " NON-isolated particles to TES " << endreq;
300     }
301     
302     return tis ;
303     
304   }
305 
306 
307   //-------------------------------------------
308   // private: response (gap effect)
309   //------------------------------------------
310   double Isolator::gapResponse(double eta){
311     double aEta = std::abs(eta);
312     double p1 = 1.1095;
313     double p2 = -7.494*std::pow((aEta - p1),2);
314     double p3 = -25.275*std::pow((aEta - p1),2);
315     double p4 = 14.52;
316     return ((aEta>1.3)&&(aEta<1.9))?
317       1.0 - std::exp(p2 - p4*std::exp(p3)) : 1.0;
318   }
319 
320   
321   //-------------------------------------------
322   // private: isIsolated
323   //------------------------------------------
324   
325   // Checks whether a candidate particle is isolated from clusters
326   // and cells
327   
328   bool Isolator::isIsolated
329   ( MsgStream& log, 
330     ReconstructedParticleCollection::const_iterator particle,
331     std::vector<ITwoCptCell*>& storedCells,
332     std::vector<ICluster*>& storedClusters
333     
334     ){
335     
336     log << MSG::DEBUG << "\n\t Treating particle: " << *particle ;
337     
338     // Measure summed cell ET within dR cones
339     // To be used for analysis-level isolation cuts
340     measureCones(log, 
341                  particle, 
342                  !storedCells.empty(),
343                  storedCells.begin(), 
344                  storedCells.end() );
345     
346     // Things we need to remember until the end of the method
347     // If, during processing of Clusters, we identify an "associated cluster"
348     // we remember it for use if the particle is finally judged to be isolated
349     bool associated = false ;
350     ICluster* associatedCluster = 0 ;
351     
352 
353 
354     //....................................
355     // Cluster isolation
356 
357     if( !storedClusters.empty() ) {
358       
359       // Make a local copy as we want to mutate the list of pointers
360       std::vector<ICluster*>  clusters( 
361                                       storedClusters.begin(), 
362                                       storedClusters.end() 
363                                       );
364      
365       if(m_fastShower){  
366          // My own test: would be removed
367        std::vector<ICluster*>::iterator it;
368        for (it=clusters.begin(); it!=clusters.end(); ++it) {
369          double dR = m_kinehelp.deltaR(*particle,*it);
370          if (dR>m_rClusterMatch) continue;
371          log << "\n\t -->  cluster: " << *it ;
372          log << "\n\t -->   DeltaR: " << dR;
373          log << "\n\t -->  EtC-EtP: "
374              << (*it)->eT() -
375            (*particle)->eT()*gapResponse((*particle)->eta());
376          log << "\n\t ---------------------------------------- " <<endreq;
377        }
378       }
379 
380       //Only use clusters not already claimed by ReconstructedParticles
381       std::vector<ICluster*>::iterator firstNonAssociatedCluster ;
382       firstNonAssociatedCluster = 
383         std::partition(
384                        clusters.begin(),
385                        clusters.end(),
386                        IsAssociated<ReconstructedParticle>
387                        );
388       if(firstNonAssociatedCluster != clusters.begin()){
389         log<<MSG::DEBUG<<"First "
390            <<firstNonAssociatedCluster-clusters.begin()
391            <<" clusters are associated to ReconstructedParticles "
392            <<clusters.end()-firstNonAssociatedCluster
393            <<" cluster(s) remain"
394            <<endreq;
395       }else{
396         log<<MSG::DEBUG
397            <<"No clusters are associated to ReconstructedParticles"
398            <<endreq;
399       }
400       if(clusters.end()!=firstNonAssociatedCluster){
401         
402         // .....................
403         // Associate unclaimed clusters with current particle. 
404         // This looks at the nearest cluster only, and decides whether
405         // it is within an "association" cone
406         
407         partial_sort(
408                      firstNonAssociatedCluster,
409                      firstNonAssociatedCluster+1,
410                      clusters.end(), 
411                      SortAttribute::DeltaR( *particle )
412                      );
413         
414         log<<MSG::DEBUG<<"Sorted clusters "<<endreq;
415         
416         associated =
417           (m_kinehelp.deltaR(*particle, *firstNonAssociatedCluster) <  
418            m_rClusterMatch);
419         
420         if( associated ) 
421           {
422             log << "\n\t -->Found associated cluster: "  
423                 << *clusters.begin() ;
424             
425             // Remember the relevant cluster until the end of this method
426             associatedCluster = *firstNonAssociatedCluster ;
427             
428             // Set the first nonassociated cluster
429             ++firstNonAssociatedCluster;
430             
431           }
432         
433         
434         //............................................
435         // Now we can check Cluster Isolation 
436         // (if there is at least one more cluster to check)
437         
438         // Use kinematic helper to do all work
439         double eClusterSum = m_kinehelp.sumETInCone( 
440                                                     firstNonAssociatedCluster, 
441                                                     clusters.end(), 
442                                                     *particle,
443                                                     m_rClusterIsolation
444                                                     );
445         
446         // Apply the cut criteria
447         
448         if( eClusterSum  > m_eClusterIsolation ) 
449           log  << "\n\t -->Excess Cluster energy in cone = " << eClusterSum 
450                << "   => NOT-ISOLATED " << endreq;       
451         else
452           log  << "\n\t -->Excess Cluster energy in cone = " << eClusterSum 
453                << "   => ISOLATED "  ;
454         
455         if( eClusterSum  > m_eClusterIsolation )  return false ;
456         
457       }
458       
459     }
460     
461     //............................................
462     // Cell Isolation: 
463    if( !storedCells.empty() ) {
464     if(!m_fastShower){  
465          
466       // Test on isolation in respect of the total transverese energy of all 
467       // Cells within a given r-cone
468       
469       // Use kinematic helper to do all work
470       double eCellSum = m_kinehelp.sumETInCone( 
471                                                storedCells.begin(), 
472                                                storedCells.end(), 
473                                                *particle,
474                                                m_rCellIsolation
475                                                );
476       
477       
478       // Subtract the energy associated with particle under test
479       // as the cells summed will have included its deposit
480       //    CalSelect depositsInCal;
481       //    if(depositsInCal( *particle) ) eCellSum -= (*particle)->eT() ;
482       bool itDeposits = m_visibleToCal->operator()( (*particle)->truth() );
483       
484       if(itDeposits) eCellSum -= (*particle)->eT() ;
485       
486       
487       // Apply isolation criteria
488       
489       if( eCellSum  > m_eCellIsolation ) 
490         log  
491           << "\n\t -->Excess Cell energy in cone = " << eCellSum 
492           << "   => NOT-ISOLATED " << endreq ;    
493       else
494         log   
495           << "\n\t -->Excess Cell energy in cone = " << eCellSum 
496           << "   => ISOLATED " << endreq ;
497       
498       if( eCellSum  > m_eCellIsolation ) return false ;
499       
500      } else { // do the following for fast shower
501       
502       // Test on isolation in respect of the total transverese energy of all
503       // Cells within a given r-cone
504 
505 
506       // dummy ReconstructedParticle to heve simple access to
507       // unsmeared 4-vector to do isolation
508       ReconstructedParticle* rp =
509         new ReconstructedParticle(
510                                   (*particle)->pdg_id(),
511                                   (*particle)->momentum(),
512                                   (*particle)->truth()
513                                   );
514 
515 
516       // Use kinematic helper to do all work
517       double eCoreSum = m_kinehelp.sumETInCone(
518                                                storedCells.begin(),
519                                                storedCells.end(),
520                                                rp,
521                                                m_rCellIsolation
522                                                );
523 
524 
525       // delete the dummy ReconstructedParticle
526       delete rp;
527 
528 
529       // Subtract the energy associated with particle under test
530       // as the cells summed will have included its deposit
531       //    CalSelect depositsInCal;
532       //    if(depositsInCal( *particle) ) eCellSum -= (*particle)->eT() ;
533       bool itDeposits = m_visibleToCal->operator()( (*particle)->truth() );
534 
535 
536       // consider the effect of transition region (from FastShower)
537       log << "\n\t -->Applying gap correction factor: "
538           << gapResponse((*particle)->eta()) << endreq ;
539 
540       double eCoreIsolation = eCoreSum;
541       if(itDeposits) eCoreIsolation -=
542                        ((*particle)->eT())*gapResponse((*particle)->eta());
543 
544       // Apply isolation criteria
545 
546       if( eCoreIsolation  > m_eCellIsolation )
547         log
548           << "\n\t -->Excess energy in core (R<0.2) = " << eCoreIsolation
549           << "   => NOT-ISOLATED " << endreq ;
550       else
551         log
552           << "\n\t -->Excess energy in core (R<0.2) = " << eCoreIsolation
553           << "   => ISOLATED " << endreq ;
554 
555       if( eCoreIsolation  > m_eCellIsolation )return false;
556      }
557     }
558 
559    
560     //..........................................
561     // If we get here then the candidate was judged to be isolated
562     
563     // It is only now that we wish to set associations between isolated
564     // particles and clusters. I.e we dont want to flag associations for 
565     // non-isolated particles
566   if( associated ) {
567       // Set the association from Particle -> Cluster
568       IAOO* iamp = *particle;
569       iamp->associate( associatedCluster ) ;
570 
571       log  << MSG::DEBUG
572            << "Particle of type "<< (*particle)->pdg_id()<<" associated to Cluster"
573            << endreq;
574       //assert(IsAssociated<Cluster>( *particle ));
575 
576       // Set the association from Cluster -> Particle
577       IAOO* iamc = associatedCluster;
578       iamc->associate( *particle ) ;
579 
580       log  << MSG::DEBUG
581            << "Cluster associated to Particle of type "<< (*particle)->pdg_id()
582            << endreq;
583 
584       //assert(IsAssociated<ReconstructedParticle>( associatedCluster ));
585    } // end of associated
586      
587     log << endreq ;
588     
589     return true ;
590   } // end of isIsolated method
591 
592   void Isolator::measureCones(
593                               MsgStream& log,
594                               ReconstructedParticleCollection::const_iterator particle,
595                               bool useCells,
596                               std::vector<ITwoCptCell*>::iterator firstCell,
597                               std::vector<ITwoCptCell*>::iterator lastCell
598                               ){
599     
600     // Initialise etcone variables
601     double etcone10 = 0, etcone20 = 0, etcone30 = 0, etcone40 = 0;
602     
603     //............................................
604     // Cell isolation: 
605     
606     if ( useCells ){
607       
608       if ( m_smearCells && m_cellSmearer ){
609         
610         etcone10 += m_kinehelp.sumSmearedETInCone( firstCell, lastCell, *particle, 0.1, m_cellSmearer );
611         etcone20 += m_kinehelp.sumSmearedETInCone( firstCell, lastCell, *particle, 0.2, m_cellSmearer );
612         etcone30 += m_kinehelp.sumSmearedETInCone( firstCell, lastCell, *particle, 0.3, m_cellSmearer );
613         etcone40 += m_kinehelp.sumSmearedETInCone( firstCell, lastCell, *particle, 0.4, m_cellSmearer );
614         
615 
616       } else {
617         etcone10 += m_kinehelp.sumETInCone( firstCell, lastCell, *particle, 0.1 );
618         etcone20 += m_kinehelp.sumETInCone( firstCell, lastCell, *particle, 0.2 );
619         etcone30 += m_kinehelp.sumETInCone( firstCell, lastCell, *particle, 0.3 );
620         etcone40 += m_kinehelp.sumETInCone( firstCell, lastCell, *particle, 0.4 );
621       }
622       
623       // Subtract the energy associated with particle under test
624       // as the cells summed will have included its deposit
625       //    CalSelect depositsInCal;
626       //    if(depositsInCal( *particle) ) eCellSum -= (*particle)->eT() ;
627       bool itDeposits = m_visibleToCal->operator()( (*particle)->truth() );
628       if(itDeposits){
629         double particleET = (*particle)->eT();
630         etcone10 -= particleET ;
631         etcone20 -= particleET ;
632         etcone30 -= particleET ;
633         etcone40 -= particleET ;
634       }
635     
636     }
637     
638     (*particle)->set_etcone10(etcone10);
639     (*particle)->set_etcone20(etcone20);
640     (*particle)->set_etcone30(etcone30);
641     (*particle)->set_etcone40(etcone40);
642     
643     log << MSG::DEBUG << "etcone10 = " << (*particle)->etcone10()
644         << ", etcone20 = " << (*particle)->etcone20()
645         << ", etcone30 = " << (*particle)->etcone30()
646         << ", etcone40 = " << (*particle)->etcone40()
647         << endreq;
648   }
649   
650 } // end of namespace bracket
651 

source navigation ] diff markup ] identifier search ] general search ]

Due to the LXR bug, the updates fail sometimes to remove references to deleted files. The Saturday's full rebuilds fix these problems
This page was automatically generated by the LXR engine. Valid HTML 4.01!