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