CDF_2004_S5839831.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 // "Acosta" underlying event analysis at CDF, inc. "Swiss Cheese"
00003 
00004 #include "Rivet/Analysis.hh"
00005 #include "Rivet/Jet.hh"
00006 #include "Rivet/RivetAIDA.hh"
00007 #include "Rivet/Tools/Logging.hh"
00008 #include "Rivet/Projections/Beam.hh"
00009 #include "Rivet/Projections/ChargedFinalState.hh"
00010 #include "Rivet/Projections/FastJets.hh"
00011 #include "Rivet/Projections/TriggerCDFRun0Run1.hh"
00012 
00013 namespace Rivet {
00014 
00015 
00016   /**
00017    * @brief "Acosta" CDF underlying event analysis
00018    * @author Andy Buckley
00019    */
00020   class CDF_2004_S5839831 : public Analysis {
00021   public:
00022 
00023     /// Constructor: cuts on charged final state are \f$ -1 < \eta < 1 \f$
00024     /// and \f$ p_T > 0.4 \f$ GeV.
00025     CDF_2004_S5839831()
00026       : Analysis("CDF_2004_S5839831")
00027     {
00028       setBeams(PROTON, ANTIPROTON);
00029     }
00030 
00031 
00032   private:
00033 
00034     struct ConesInfo {
00035       ConesInfo() : numMax(0), numMin(0), ptMax(0), ptMin(0), ptDiff(0) {}
00036       unsigned int numMax, numMin;
00037       double ptMax, ptMin, ptDiff;
00038     };
00039  
00040  
00041     ConesInfo _calcTransCones(const double etaLead, const double phiLead,
00042                               const ParticleVector& tracks) {
00043       const double phiTransPlus = mapAngle0To2Pi(phiLead + PI/2.0);
00044       const double phiTransMinus = mapAngle0To2Pi(phiLead - PI/2.0);
00045       getLog() << Log::DEBUG << "phi_lead = " << phiLead
00046                << " -> trans = (" << phiTransPlus
00047                << ", " << phiTransMinus << ")" << endl;
00048    
00049       unsigned int numPlus(0), numMinus(0);
00050       double ptPlus(0), ptMinus(0);
00051       // Run over all charged tracks
00052       foreach (const Particle& t, tracks) {
00053         FourMomentum trackMom = t.momentum();
00054         const double pt = trackMom.pT();
00055      
00056         // Find if track mom is in either transverse cone
00057         if (deltaR(trackMom, etaLead, phiTransPlus) < 0.7) {
00058           ptPlus += pt;
00059           numPlus += 1;
00060         } else if (deltaR(trackMom, etaLead, phiTransMinus) < 0.7) {
00061           ptMinus += pt;
00062           numMinus += 1;
00063         }
00064       }
00065    
00066       ConesInfo rtn;
00067       // Assign N_{min,max} from N_{plus,minus}
00068       rtn.numMax = (ptPlus >= ptMinus) ? numPlus : numMinus;
00069       rtn.numMin = (ptPlus >= ptMinus) ? numMinus : numPlus;
00070       // Assign pT_{min,max} from pT_{plus,minus}
00071       rtn.ptMax = (ptPlus >= ptMinus) ? ptPlus : ptMinus;
00072       rtn.ptMin = (ptPlus >= ptMinus) ? ptMinus : ptPlus;
00073       rtn.ptDiff = fabs(rtn.ptMax - rtn.ptMin);
00074    
00075       getLog() << Log::DEBUG << "Min cone has " << rtn.numMin << " tracks -> "
00076                << "pT_min = " << rtn.ptMin/GeV << " GeV" << endl;
00077       getLog() << Log::DEBUG << "Max cone has " << rtn.numMax << " tracks -> "
00078                << "pT_max = " << rtn.ptMax/GeV << " GeV" << endl;
00079    
00080       return rtn;
00081     }
00082  
00083  
00084     ConesInfo _calcTransCones(const FourMomentum& leadvec,
00085                               const ParticleVector& tracks) {
00086       const double etaLead = leadvec.pseudorapidity();
00087       const double phiLead = leadvec.azimuthalAngle();
00088       return _calcTransCones(etaLead, phiLead, tracks);
00089     }
00090 
00091 
00092     /// @name Analysis methods
00093     //@{
00094  
00095     void init() {
00096       // Set up projections
00097       addProjection(TriggerCDFRun0Run1(), "Trigger");
00098       addProjection(Beam(), "Beam");
00099       const FinalState calofs(-1.2, 1.2);
00100       addProjection(calofs, "CaloFS");
00101       addProjection(FastJets(calofs, FastJets::CDFJETCLU, 0.7), "Jets");
00102       const ChargedFinalState trackfs(-1.2, 1.2, 0.4*GeV);
00103       addProjection(trackfs, "TrackFS");
00104       // Restrict tracks to |eta| < 0.7 for the min bias part.
00105       const ChargedFinalState mbfs(-0.7, 0.7, 0.4*GeV);
00106       addProjection(mbfs, "MBFS");
00107       // Restrict tracks to |eta| < 1 for the Swiss-Cheese part.
00108       const ChargedFinalState cheesefs(-1.0, 1.0, 0.4*GeV);
00109       addProjection(cheesefs, "CheeseFS");
00110       addProjection(FastJets(cheesefs, FastJets::CDFJETCLU, 0.7), "CheeseJets");
00111 
00112       // Book histograms
00113       if (fuzzyEquals(sqrtS()/GeV, 1800, 1E-3)) {
00114         _pt90MaxAvg1800 = bookProfile1D(1, 1, 1);
00115         _pt90MinAvg1800 = bookProfile1D(1, 1, 2);
00116         _pt90Max1800 = bookProfile1D(2, 1, 1);
00117         _pt90Min1800 = bookProfile1D(2, 1, 2);
00118         _pt90Diff1800 = bookProfile1D(2, 1, 3);
00119         _num90Max1800 = bookProfile1D(4, 1, 1);
00120         _num90Min1800 = bookProfile1D(4, 1, 2);
00121         _pTSum1800_2Jet = bookProfile1D(7, 1, 1);
00122         _pTSum1800_3Jet = bookProfile1D(7, 1, 2);
00123 
00124         _pt90Dbn1800Et40 = bookHistogram1D(3, 1, 1);
00125         _pt90Dbn1800Et80 = bookHistogram1D(3, 1, 2);
00126         _pt90Dbn1800Et120 = bookHistogram1D(3, 1, 3);
00127         _pt90Dbn1800Et160 = bookHistogram1D(3, 1, 4);
00128         _pt90Dbn1800Et200 = bookHistogram1D(3, 1, 5);
00129         _numTracksDbn1800MB = bookHistogram1D(5, 1, 1);
00130         _ptDbn1800MB = bookHistogram1D(6, 1, 1);
00131       } else if (fuzzyEquals(sqrtS()/GeV, 630, 1E-3)) {
00132         _pt90Max630 = bookProfile1D(8, 1, 1);
00133         _pt90Min630 = bookProfile1D(8, 1, 2);
00134         _pt90Diff630 = bookProfile1D(8, 1, 3);
00135         _pTSum630_2Jet = bookProfile1D(9, 1, 1);
00136         _pTSum630_3Jet = bookProfile1D(9, 1, 2);
00137 
00138         _numTracksDbn630MB = bookHistogram1D(10, 1, 1);
00139         _ptDbn630MB = bookHistogram1D(11, 1, 1);
00140       }
00141     }
00142  
00143  
00144     /// Do the analysis
00145     void analyze(const Event& event) {
00146       // Trigger
00147       const bool trigger = applyProjection<TriggerCDFRun0Run1>(event, "Trigger").minBiasDecision();
00148       if (!trigger) vetoEvent;
00149 
00150       // Get sqrt(s) and event weight
00151       const double sqrtS = applyProjection<Beam>(event, "Beam").sqrtS();
00152       const double weight = event.weight();
00153    
00154       {
00155         getLog() << Log::DEBUG << "Running max/min analysis" << endl;
00156         vector<Jet> jets = applyProjection<JetAlg>(event, "Jets").jetsByE();
00157         if (!jets.empty()) {
00158           // Leading jet must be in central |eta| < 0.5 region
00159           const Jet leadingjet = jets.front();
00160           const double etaLead = leadingjet.momentum().eta();
00161           // Get Et of the leading jet: used to bin histograms
00162           const double ETlead = leadingjet.EtSum();
00163           getLog() << Log::DEBUG << "Leading Et = " << ETlead/GeV << " GeV" << endl;
00164           if (fabs(etaLead) > 0.5 && ETlead < 15*GeV) {
00165             getLog() << Log::DEBUG << "Leading jet eta = " << etaLead
00166                      << " not in |eta| < 0.5 & pT > 15 GeV" << endl;
00167           } else {
00168             // Multiplicity & pT distributions for sqrt(s) = 630 GeV, 1800 GeV
00169             const ParticleVector tracks = applyProjection<FinalState>(event, "TrackFS").particles();
00170             const ConesInfo cones = _calcTransCones(leadingjet.momentum(), tracks);
00171             if (fuzzyEquals(sqrtS/GeV, 630)) {
00172               _pt90Max630->fill(ETlead/GeV, cones.ptMax/GeV, weight);
00173               _pt90Min630->fill(ETlead/GeV, cones.ptMin/GeV, weight);
00174               _pt90Diff630->fill(ETlead/GeV, cones.ptDiff/GeV, weight);
00175             } else if (fuzzyEquals(sqrtS/GeV, 1800)) {
00176               _num90Max1800->fill(ETlead/GeV, cones.numMax, weight);
00177               _num90Min1800->fill(ETlead/GeV, cones.numMin, weight);
00178               _pt90Max1800->fill(ETlead/GeV, cones.ptMax/GeV, weight);
00179               _pt90Min1800->fill(ETlead/GeV, cones.ptMin/GeV, weight);
00180               _pt90Diff1800->fill(ETlead/GeV, cones.ptDiff/GeV, weight);
00181               _pt90MaxAvg1800->fill(ETlead/GeV, cones.ptMax/GeV, weight); // /numMax
00182               _pt90MinAvg1800->fill(ETlead/GeV, cones.ptMin/GeV, weight); // /numMin
00183               //
00184               const double ptTransTotal = cones.ptMax + cones.ptMin;
00185               if (inRange(ETlead/GeV, 40., 80.)) {
00186                 _pt90Dbn1800Et40->fill(ptTransTotal/GeV, weight);
00187               } else if (inRange(ETlead/GeV, 80., 120.)) {
00188                 _pt90Dbn1800Et80->fill(ptTransTotal/GeV, weight);
00189               } else if (inRange(ETlead/GeV, 120., 160.)) {
00190                 _pt90Dbn1800Et120->fill(ptTransTotal/GeV, weight);
00191               } else if (inRange(ETlead/GeV, 160., 200.)) {
00192                 _pt90Dbn1800Et160->fill(ptTransTotal/GeV, weight);
00193               } else if (inRange(ETlead/GeV, 200., 270.)) {
00194                 _pt90Dbn1800Et200->fill(ptTransTotal/GeV, weight);
00195               }
00196             }
00197          
00198           }
00199         }
00200       }
00201    
00202    
00203       // Fill min bias total track multiplicity histos
00204       {
00205         getLog() << Log::DEBUG << "Running min bias multiplicity analysis" << endl;
00206         const ParticleVector mbtracks = applyProjection<FinalState>(event, "MBFS").particles();
00207         if (fuzzyEquals(sqrtS/GeV, 1800)) {
00208           _numTracksDbn1800MB->fill(mbtracks.size(), weight);
00209         } else if (fuzzyEquals(sqrtS/GeV, 630)) {
00210           _numTracksDbn630MB->fill(mbtracks.size(), weight);
00211         }
00212         // Run over all charged tracks
00213         foreach (const Particle& t, mbtracks) {
00214           FourMomentum trackMom = t.momentum();
00215           const double pt = trackMom.pT();
00216           // Plot total pT distribution for min bias
00217           if (fuzzyEquals(sqrtS/GeV, 1800)) {
00218             _ptDbn1800MB->fill(pt/GeV, weight);
00219           } else if (fuzzyEquals(sqrtS/GeV, 630)) {
00220             _ptDbn630MB->fill(pt/GeV, weight);
00221           }
00222         }
00223       }
00224    
00225    
00226    
00227       // Construct "Swiss Cheese" pT distributions, with pT contributions from
00228       // tracks within R = 0.7 of the 1st, 2nd (and 3rd) jets being ignored. A
00229       // different set of charged tracks, with |eta| < 1.0, is used here, and all
00230       // the removed jets must have Et > 5 GeV.
00231       {
00232         getLog() << Log::DEBUG << "Running Swiss Cheese analysis" << endl;
00233         const ParticleVector cheesetracks = applyProjection<FinalState>(event, "CheeseFS").particles();
00234         vector<Jet> cheesejets = applyProjection<JetAlg>(event, "Jets").jetsByE();
00235         if (cheesejets.empty()) {
00236           getLog() << Log::DEBUG << "No 'cheese' jets found in event" << endl;
00237           return;
00238         }
00239         if (cheesejets.size() > 1 &&
00240             fabs(cheesejets[0].momentum().pseudorapidity()) <= 0.5 &&
00241             cheesejets[0].momentum().Et()/GeV > 5.0 &&
00242             cheesejets[1].momentum().Et()/GeV > 5.0) {
00243        
00244           const double cheeseETlead = cheesejets[0].momentum().Et();
00245        
00246           const double eta1 = cheesejets[0].momentum().pseudorapidity();
00247           const double phi1 = cheesejets[0].momentum().azimuthalAngle();
00248           const double eta2 = cheesejets[1].momentum().pseudorapidity();
00249           const double phi2 = cheesejets[1].momentum().azimuthalAngle();
00250        
00251           double ptSumSub2(0), ptSumSub3(0);
00252           foreach (const Particle& t, cheesetracks) {
00253             FourMomentum trackMom = t.momentum();
00254             const double pt = trackMom.pT();
00255          
00256             // Subtracting 2 leading jets
00257             const double deltaR1 = deltaR(trackMom, eta1, phi1);
00258             const double deltaR2 = deltaR(trackMom, eta2, phi2);
00259             getLog() << Log::TRACE << "Track vs jet(1): "
00260                      << "|(" << trackMom.pseudorapidity() << ", " << trackMom.azimuthalAngle() << ") - "
00261                      << "|(" << eta1 << ", " << phi1 << ")| = " << deltaR1 << endl;
00262             getLog() << Log::TRACE << "Track vs jet(2): "
00263                      << "|(" << trackMom.pseudorapidity() << ", " << trackMom.azimuthalAngle() << ") - "
00264                      << "|(" << eta2 << ", " << phi2 << ")| = " << deltaR2 << endl;
00265             if (deltaR1 > 0.7 && deltaR2 > 0.7) {
00266               ptSumSub2 += pt;
00267            
00268               // Subtracting 3rd leading jet
00269               if (cheesejets.size() > 2 &&
00270                   cheesejets[2].momentum().Et()/GeV > 5.0) {
00271                 const double eta3 = cheesejets[2].momentum().pseudorapidity();
00272                 const double phi3 = cheesejets[2].momentum().azimuthalAngle();
00273                 const double deltaR3 = deltaR(trackMom, eta3, phi3);
00274                 getLog() << Log::TRACE << "Track vs jet(3): "
00275                          << "|(" << trackMom.pseudorapidity() << ", " << trackMom.azimuthalAngle() << ") - "
00276                          << "|(" << eta3 << ", " << phi3 << ")| = " << deltaR3 << endl;
00277                 if (deltaR3 > 0.7) {
00278                   ptSumSub3 += pt;
00279                 }
00280               }
00281             }
00282           }
00283        
00284           // Swiss Cheese sub 2,3 jets distributions for sqrt(s) = 630 GeV, 1800 GeV
00285           if (fuzzyEquals(sqrtS/GeV, 630)) {
00286             if (!isZero(ptSumSub2)) _pTSum630_2Jet->fill(cheeseETlead/GeV, ptSumSub2/GeV, weight);
00287             if (!isZero(ptSumSub3))_pTSum630_3Jet->fill(cheeseETlead/GeV, ptSumSub3/GeV, weight);
00288           } else if (fuzzyEquals(sqrtS/GeV, 1800)) {
00289             if (!isZero(ptSumSub2))_pTSum1800_2Jet->fill(cheeseETlead/GeV, ptSumSub2/GeV, weight);
00290             if (!isZero(ptSumSub3))_pTSum1800_3Jet->fill(cheeseETlead/GeV, ptSumSub3/GeV, weight);
00291           }
00292        
00293         }
00294       }
00295    
00296     }
00297  
00298  
00299     void finalize() {
00300       /// @todo Take these normalisations from the data histo (it can't come from just the MC)
00301 
00302       if (fuzzyEquals(sqrtS()/GeV, 1800, 1E-3)) {
00303         // Normalize to actual number of entries in pT dbn histos...
00304         normalize(_pt90Dbn1800Et40,  1656.75); // norm OK
00305         normalize(_pt90Dbn1800Et80,  4657.5); // norm OK
00306         normalize(_pt90Dbn1800Et120, 5395.5); // norm OK
00307         normalize(_pt90Dbn1800Et160, 7248.75); // norm OK
00308         normalize(_pt90Dbn1800Et200, 2442.0); // norm OK
00309       }
00310    
00311       // ...and for min bias distributions:
00312       if (fuzzyEquals(sqrtS()/GeV, 1800, 1E-3)) {
00313         normalize(_numTracksDbn1800MB, 309718.25); // norm OK
00314         normalize(_ptDbn1800MB, 33600.0); // norm OK
00315       } else if (fuzzyEquals(sqrtS()/GeV, 630, 1E-3)) {
00316         normalize(_numTracksDbn630MB, 1101024.0); // norm OK
00317         normalize(_ptDbn630MB, 105088.0); // norm OK
00318       }
00319     }
00320 
00321     //@}
00322 
00323 
00324   private:
00325 
00326     /// @name Histogram collections
00327     //@{
00328     /// Profile histograms, binned in the \f$ E_T \f$ of the leading jet, for
00329     /// the average \f$ p_T \f$ in the toward, transverse and away regions at
00330     /// \f$ \sqrt{s} = 1800 \text{GeV} \f$.
00331     /// Corresponds to Table 1, and HepData table 1.
00332     AIDA::IProfile1D *_pt90MaxAvg1800, *_pt90MinAvg1800;
00333 
00334     /// Profile histograms, binned in the \f$ E_T \f$ of the leading jet, for
00335     /// the \f$ p_T \f$ sum in the toward, transverse and away regions at
00336     /// \f$ \sqrt{s} = 1800 \text{GeV} \f$.
00337     /// Corresponds to figure 2/3, and HepData table 2.
00338     AIDA::IProfile1D *_pt90Max1800, *_pt90Min1800, *_pt90Diff1800;
00339 
00340     /// Profile histograms, binned in the \f$ E_T \f$ of the leading jet, for
00341     /// the \f$ p_T \f$ sum in the toward, transverse and away regions at
00342     /// at \f$ \sqrt{s} = 630 \text{GeV} \f$.
00343     /// Corresponds to figure 8, and HepData table 8.
00344     AIDA::IProfile1D *_pt90Max630, *_pt90Min630, *_pt90Diff630;
00345 
00346     /// Profile histograms, binned in the \f$ E_T \f$ of the leading jet, for
00347     /// the cone track multiplicity at \f$ \sqrt{s} = 1800 \text{GeV} \f$.
00348     /// Corresponds to figure 5, and HepData table 4.
00349     AIDA::IProfile1D *_num90Max1800, *_num90Min1800;
00350 
00351     /// Profile histograms, binned in the \f$ E_T \f$ of the leading jet, for
00352     /// the \f$ p_T \f$ sum at \f$ \sqrt{s} = 1800 \text{GeV} \f$.
00353     /// Corresponds to figure 7, and HepData table 7.
00354     AIDA::IProfile1D *_pTSum1800_2Jet, *_pTSum1800_3Jet;
00355 
00356     /// Profile histograms, binned in the \f$ E_T \f$ of the leading jet, for
00357     /// the \f$ p_T \f$ sum at \f$ \sqrt{s} = 630 \text{GeV} \f$.
00358     /// Corresponds to figure 9, and HepData table 9.
00359     AIDA::IProfile1D *_pTSum630_2Jet, *_pTSum630_3Jet;
00360 
00361     /// Histogram of \f$ p_{T\text{sum}} \f$ distribution for 5 different
00362     /// \f$ E_{T1} \f$ bins.
00363     /// Corresponds to figure 4, and HepData table 3.
00364     AIDA::IHistogram1D *_pt90Dbn1800Et40, *_pt90Dbn1800Et80, *_pt90Dbn1800Et120,
00365       *_pt90Dbn1800Et160, *_pt90Dbn1800Et200;
00366 
00367     /// Histograms of track multiplicity and \f$ p_T \f$ distributions for
00368     /// minimum bias events.
00369     /// Figure 6, and HepData tables 5 & 6.
00370     /// Figure 10, and HepData tables 10 & 11.
00371     AIDA::IHistogram1D *_numTracksDbn1800MB, *_ptDbn1800MB;
00372     AIDA::IHistogram1D *_numTracksDbn630MB, *_ptDbn630MB;
00373     //@}
00374  
00375   };
00376  
00377  
00378 
00379   // This global object acts as a hook for the plugin system
00380   AnalysisBuilder<CDF_2004_S5839831> plugin_CDF_2004_S5839831;
00381 
00382 }