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