rivet is hosted by Hepforge, IPPP Durham
ATLAS_2011_I944826.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Analysis.hh"
00003 #include "Rivet/Projections/ChargedFinalState.hh"
00004 #include "Rivet/Projections/IdentifiedFinalState.hh"
00005 #include "Rivet/Projections/UnstableFinalState.hh"
00006 
00007 namespace Rivet {
00008 
00009 
00010   class ATLAS_2011_I944826 : public Analysis {
00011   public:
00012 
00013     /// Constructor
00014     ATLAS_2011_I944826()
00015       : Analysis("ATLAS_2011_I944826")
00016     {
00017       _sum_w_ks     = 0.0;
00018       _sum_w_lambda = 0.0;
00019       _sum_w_passed = 0.0;
00020     }
00021 
00022 
00023     /// Book histograms and initialise projections before the run
00024     void init() {
00025 
00026       UnstableFinalState ufs(Cuts::pT > 100*MeV);
00027       addProjection(ufs, "UFS");
00028 
00029       ChargedFinalState  mbts(Cuts::absetaIn(2.09, 3.84));
00030       addProjection(mbts, "MBTS");
00031 
00032       IdentifiedFinalState nstable(Cuts::abseta < 2.5 && Cuts::pT >= 100*MeV);
00033       nstable.acceptIdPair(PID::ELECTRON)
00034         .acceptIdPair(PID::MUON)
00035         .acceptIdPair(PID::PIPLUS)
00036         .acceptIdPair(PID::KPLUS)
00037         .acceptIdPair(PID::PROTON);
00038       addProjection(nstable, "nstable");
00039 
00040       if (fuzzyEquals(sqrtS()/GeV, 7000, 1e-3)) {
00041         _hist_Ks_pT      = bookHisto1D(1, 1, 1);
00042         _hist_Ks_y       = bookHisto1D(2, 1, 1);
00043         _hist_Ks_mult    = bookHisto1D(3, 1, 1);
00044         _hist_L_pT       = bookHisto1D(7, 1, 1);
00045         _hist_L_y        = bookHisto1D(8, 1, 1);
00046         _hist_L_mult     = bookHisto1D(9, 1, 1);
00047         _hist_Ratio_v_y  = bookScatter2D(13, 1, 1);
00048         _hist_Ratio_v_pT = bookScatter2D(14, 1, 1);
00049         //
00050         _temp_lambda_v_y = Histo1D(10, 0.0, 2.5);
00051         _temp_lambdabar_v_y = Histo1D(10, 0.0, 2.5);
00052         _temp_lambda_v_pT = Histo1D(18, 0.5, 4.1);
00053         _temp_lambdabar_v_pT = Histo1D(18, 0.5, 4.1);
00054       }
00055       else if (fuzzyEquals(sqrtS()/GeV, 900, 1E-3)) {
00056         _hist_Ks_pT   = bookHisto1D(4, 1, 1);
00057         _hist_Ks_y    = bookHisto1D(5, 1, 1);
00058         _hist_Ks_mult = bookHisto1D(6, 1, 1);
00059         _hist_L_pT    = bookHisto1D(10, 1, 1);
00060         _hist_L_y     = bookHisto1D(11, 1, 1);
00061         _hist_L_mult  = bookHisto1D(12, 1, 1);
00062         _hist_Ratio_v_y      = bookScatter2D(15, 1, 1);
00063         _hist_Ratio_v_pT     = bookScatter2D(16, 1, 1);
00064         //
00065         _temp_lambda_v_y = Histo1D(5, 0.0, 2.5);
00066         _temp_lambdabar_v_y = Histo1D(5, 0.0, 2.5);
00067         _temp_lambda_v_pT = Histo1D(8, 0.5, 3.7);
00068         _temp_lambdabar_v_pT = Histo1D(8, 0.5, 3.7);
00069       }
00070     }
00071 
00072 
00073     // This function is required to impose the flight time cuts on Kaons and Lambdas
00074     double getPerpFlightDistance(const Rivet::Particle& p) {
00075       const HepMC::GenParticle* genp = p.genParticle();
00076       const HepMC::GenVertex* prodV = genp->production_vertex();
00077       const HepMC::GenVertex* decV  = genp->end_vertex();
00078       const HepMC::ThreeVector prodPos = prodV->point3d();
00079       if (decV) {
00080         const HepMC::ThreeVector decPos = decV->point3d();
00081         double dy = prodPos.y() - decPos.y();
00082         double dx = prodPos.x() - decPos.x();
00083         return add_quad(dx, dy);
00084       }
00085       return numeric_limits<double>::max();
00086     }
00087 
00088 
00089     bool daughtersSurviveCuts(const Rivet::Particle& p) {
00090       // We require the Kshort or Lambda to decay into two charged
00091       // particles with at least pT = 100 MeV inside acceptance region
00092       const HepMC::GenParticle* genp = p.genParticle();
00093       const HepMC::GenVertex* decV  = genp->end_vertex();
00094       bool decision = true;
00095 
00096       if (!decV) return false;
00097       if (decV->particles_out_size() == 2) {
00098         std::vector<double> pTs;
00099         std::vector<int> charges;
00100         std::vector<double> etas;
00101         foreach (const HepMC::GenParticle* gp, particles(decV, HepMC::children)) {
00102           pTs.push_back(gp->momentum().perp());
00103           etas.push_back(fabs(gp->momentum().eta()));
00104           charges.push_back( Rivet::PID::threeCharge(gp->pdg_id()) );
00105           // gp->print();
00106         }
00107         if ( (pTs[0]/Rivet::GeV < 0.1) || (pTs[1]/Rivet::GeV < 0.1) ) {
00108           decision = false;
00109           MSG_DEBUG("Failed pT cut: " << pTs[0]/Rivet::GeV << " " << pTs[1]/Rivet::GeV);
00110         }
00111         if ( etas[0] > 2.5 || etas[1] > 2.5 ) {
00112           decision = false;
00113           MSG_DEBUG("Failed eta cut: " << etas[0] << " " << etas[1]);
00114         }
00115         if ( charges[0] * charges[1] >= 0 ) {
00116           decision = false;
00117           MSG_DEBUG("Failed opposite charge cut: " << charges[0] << " " << charges[1]);
00118         }
00119       }
00120       else {
00121         decision = false;
00122         MSG_DEBUG("Failed nDaughters cut: " << decV->particles_out_size());
00123       }
00124 
00125       return decision;
00126     }
00127 
00128     /// Perform the per-event analysis
00129     void analyze(const Event& event) {
00130       const double weight = event.weight();
00131 
00132       // ATLAS MBTS trigger requirement of at least one hit in either hemisphere
00133       if (applyProjection<FinalState>(event, "MBTS").size() < 1) {
00134         MSG_DEBUG("Failed trigger cut");
00135         vetoEvent;
00136       }
00137 
00138       // Veto event also when we find less than 2 particles in the acceptance region of type 211,2212,11,13,321
00139       if (applyProjection<FinalState>(event, "nstable").size() < 2) {
00140         MSG_DEBUG("Failed stable particle cut");
00141         vetoEvent;
00142       }
00143       _sum_w_passed += weight;
00144 
00145       // This ufs holds all the Kaons and Lambdas
00146       const UnstableFinalState& ufs = applyProjection<UnstableFinalState>(event, "UFS");
00147 
00148       // Some conters
00149       int n_KS0 = 0;
00150       int n_LAMBDA = 0;
00151 
00152       // Particle loop
00153       foreach (const Particle& p, ufs.particles()) {
00154 
00155         // General particle quantities
00156         const double pT = p.pT();
00157         const double y = p.rapidity();
00158         const PdgId apid = p.abspid();
00159 
00160         double flightd = 0.0;
00161 
00162         // Look for Kaons, Lambdas
00163         switch (apid) {
00164 
00165         case PID::K0S:
00166           flightd = getPerpFlightDistance(p);
00167           if (!inRange(flightd/mm, 4., 450.) ) {
00168             MSG_DEBUG("Kaon failed flight distance cut:" << flightd);
00169             break;
00170           }
00171           if (daughtersSurviveCuts(p) ) {
00172             _hist_Ks_y ->fill(y, weight);
00173             _hist_Ks_pT->fill(pT/GeV, weight);
00174             _sum_w_ks += weight;
00175             n_KS0++;
00176           }
00177           break;
00178 
00179         case PID::LAMBDA:
00180           if (pT < 0.5*GeV) { // Lambdas have an additional pT cut of 500 MeV
00181             MSG_DEBUG("Lambda failed pT cut:" << pT/GeV << " GeV");
00182             break;
00183           }
00184           flightd = getPerpFlightDistance(p);
00185           if (!inRange(flightd/mm, 17., 450.)) {
00186             MSG_DEBUG("Lambda failed flight distance cut:" << flightd/mm << " mm");
00187             break;
00188           }
00189           if ( daughtersSurviveCuts(p) ) {
00190             if (p.pid() == PID::LAMBDA) {
00191               _temp_lambda_v_y.fill(fabs(y), weight);
00192               _temp_lambda_v_pT.fill(pT/GeV, weight);
00193               _hist_L_y->fill(y, weight);
00194               _hist_L_pT->fill(pT/GeV, weight);
00195               _sum_w_lambda += weight;
00196               n_LAMBDA++;
00197             } else if (p.pid() == -PID::LAMBDA) {
00198              _temp_lambdabar_v_y.fill(fabs(y), weight);
00199               _temp_lambdabar_v_pT.fill(pT/GeV, weight);
00200             }
00201           }
00202           break;
00203 
00204         }
00205       }
00206 
00207       // Fill multiplicity histos
00208       _hist_Ks_mult->fill(n_KS0, weight);
00209       _hist_L_mult->fill(n_LAMBDA, weight);
00210     }
00211 
00212 
00213 
00214     /// Normalise histograms etc., after the run
00215     void finalize() {
00216       MSG_DEBUG("# Events that pass the trigger: " << _sum_w_passed);
00217       MSG_DEBUG("# Kshort events: " << _sum_w_ks);
00218       MSG_DEBUG("# Lambda events: " << _sum_w_lambda);
00219 
00220       /// @todo Replace with normalize()?
00221       scale(_hist_Ks_pT,   1.0/_sum_w_ks);
00222       scale(_hist_Ks_y,    1.0/_sum_w_ks);
00223       scale(_hist_Ks_mult, 1.0/_sum_w_passed);
00224 
00225       /// @todo Replace with normalize()?
00226       scale(_hist_L_pT,   1.0/_sum_w_lambda);
00227       scale(_hist_L_y,    1.0/_sum_w_lambda);
00228       scale(_hist_L_mult, 1.0/_sum_w_passed);
00229 
00230       // Division of histograms to obtain lambda_bar/lambda ratios
00231       divide(_temp_lambdabar_v_y, _temp_lambda_v_y, _hist_Ratio_v_y);
00232       divide(_temp_lambdabar_v_pT, _temp_lambda_v_pT, _hist_Ratio_v_pT);
00233     }
00234 
00235 
00236   private:
00237 
00238     /// Counters
00239     double _sum_w_ks, _sum_w_lambda, _sum_w_passed;
00240 
00241     /// @name Persistent histograms
00242     //@{
00243     Histo1DPtr _hist_Ks_pT, _hist_Ks_y, _hist_Ks_mult;
00244     Histo1DPtr _hist_L_pT, _hist_L_y, _hist_L_mult;
00245     Scatter2DPtr _hist_Ratio_v_pT, _hist_Ratio_v_y;
00246     //@}
00247 
00248     /// @name Temporary histograms
00249     //@{
00250     Histo1D _temp_lambda_v_y, _temp_lambdabar_v_y;
00251     Histo1D _temp_lambda_v_pT, _temp_lambdabar_v_pT;
00252     //@}
00253 
00254   };
00255 
00256 
00257   // The hook for the plugin system
00258   DECLARE_RIVET_PLUGIN(ATLAS_2011_I944826);
00259 
00260 }