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