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