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