rivet is hosted by Hepforge, IPPP Durham
ATLAS_2011_S9108483.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Analysis.hh"
00003 #include "Rivet/Tools/BinnedHistogram.hh"
00004 #include "Rivet/RivetYODA.hh"
00005 #include "Rivet/Math/Constants.hh"
00006 #include "Rivet/Tools/ParticleIdUtils.hh"
00007 #include "Rivet/Tools/Logging.hh"
00008 #include "Rivet/Projections/ChargedFinalState.hh"
00009 #include "Rivet/Projections/NonHadronicFinalState.hh"
00010 #include "Rivet/Projections/VetoedFinalState.hh"
00011 
00012 namespace Rivet {
00013 
00014 
00015   class ATLAS_2011_S9108483 : public Analysis {
00016   public:
00017 
00018     /// @name Constructors etc.
00019     //@{
00020 
00021     /// Constructor
00022     ATLAS_2011_S9108483()
00023       : Analysis("ATLAS_2011_S9108483")
00024     {
00025     }
00026 
00027     //@}
00028 
00029 
00030   public:
00031 
00032     /// @name Analysis methods
00033     //@{
00034 
00035     /// Book histograms and initialise projections before the run
00036     void init() {
00037 
00038       // get the non-hadronic final-state particles
00039       double etaMax = 2.5;
00040       const NonHadronicFinalState nhfs(-etaMax,etaMax,13.*GeV);
00041       addProjection(nhfs,"NHFS");
00042       // select the charged ones
00043       const ChargedFinalState cfs(nhfs);
00044       addProjection(cfs,"CFS");
00045       // and then veto electrons, and taus to be safe
00046       VetoedFinalState vfs(cfs);
00047       vfs.addVetoPairId(ELECTRON);
00048 
00049       addProjection(vfs,"VFS");
00050 
00051       /// Book histograms
00052       _count_trigger   = bookHisto1D("count_trigger"  , 1, 0., 1.);
00053       _count_event     = bookHisto1D("count_selection", 1, 0., 1.);
00054       _count_quality   = bookHisto1D("count_quality"  , 1, 0., 1.);
00055       _count_beta      = bookHisto1D("count_beta"     , 1, 0., 1.);
00056       _count_90  = bookHisto1D("count_90" , 1, 0., 1.);
00057       _count_110 = bookHisto1D("count_110", 1, 0., 1.);
00058       _count_120 = bookHisto1D("count_120", 1, 0., 1.);
00059       _count_130 = bookHisto1D("count_130", 1, 0., 1.);
00060 
00061       _hist_beta = bookHisto1D("beta",1000, 0.,   2.);
00062       _hist_time = bookHisto1D("time",1000, -50,  50.);
00063       _hist_mass = bookHisto1D("mass",  60, 5., 305.);
00064     }
00065 
00066 
00067     double rndGauss(double sigma, double mean) {
00068       double r = sqrt(-2.0*log(rand()/static_cast<double>(RAND_MAX)));
00069       double phi = rand()/static_cast<double>(RAND_MAX)*2.0*pi;
00070       return mean+sigma*r*sin(phi);
00071     }
00072 
00073     /// Perform the per-event analysis
00074     void analyze(const Event& event) {
00075       // smearing parameters
00076       // time measurement (in ns)
00077 //       const double tsmear=5.*0.7;
00078       const double tsmear=0.7;
00079       // sagita error
00080       const double csag  =1.1E-4;
00081       // multiple scattering
00082       const double cms   =2.0E-2;
00083       // muon chamber radius (in metres)
00084       const double radius = 10.e3;
00085       // convert to ns
00086       const double tr = radius/c_light;
00087       // event weight
00088       const double weight = event.weight();
00089       // get the charged final-state particles
00090       ParticleVector charged =
00091         applyProjection<VetoedFinalState>(event,"VFS").particles();
00092       // need at least two candidates
00093       if(charged.size()<2) vetoEvent;
00094       // number passing trigger
00095       _count_trigger->fill(0.5,weight);
00096       // Z mass veto
00097       foreach ( const Particle & mu1,charged ) {
00098         foreach ( const Particle & mu2,charged ) {
00099           double mass = (mu1.momentum()+mu2.momentum()).mass();
00100           double diff = abs(mass-91.18);
00101           if(diff<10.) vetoEvent;
00102         }
00103       }
00104       // number passing first event selection
00105       _count_event->fill(0.5,weight);
00106       // now find the candidates
00107       // loop over the particles and find muons and heavy charged particles
00108       map<double,Particle> muonCandidates;
00109       foreach ( const Particle & mu,charged ) {
00110         // calculate the smeared momentum
00111         double pT     = mu.momentum().perp2();
00112         double pmag   = sqrt(pT+sqr(mu.momentum().z()));
00113         double deltap = sqrt( sqr(csag*sqr(pmag)) +
00114                               sqr(cms*mu.momentum().t()/GeV));
00115         double psmear = rndGauss(deltap,pmag);
00116         // keep particles with pT>40
00117         if(psmear/pmag*mu.momentum().perp()<40.*GeV||
00118            psmear/pmag*mu.momentum().perp()>1000.*GeV) continue;
00119         muonCandidates.insert(make_pair(psmear,mu));
00120       }
00121       // require two candidates
00122       if(muonCandidates.size()<2) vetoEvent;
00123       // number passing "quality" cut
00124       _count_quality->fill(0.5,weight);
00125       // now do the time of flight
00126       bool filled = false;
00127       for(map<double,Particle>::const_iterator it=muonCandidates.begin();
00128           it!=muonCandidates.end();++it) {
00129         // true magnitude and pT of momentum
00130         double pT     = it->second.momentum().perp2();
00131         double pmag   = sqrt(pT+sqr(it->second.momentum().z()));
00132         pT = sqrt(pT);
00133         // true time difference in ns
00134         double deltaT  =tr *(it->second.momentum().t()-pmag)/pT;
00135         // smear it
00136         deltaT = rndGauss(tsmear,deltaT);
00137         // beta
00138         double beta = 1./(1.+deltaT/tr*pT/pmag);
00139         _hist_beta->fill(beta, weight);
00140         _hist_time->fill(deltaT, weight);
00141         // beta cut
00142         if(beta<0.95) continue;
00143         // mass
00144         double mass = 2.*pT*it->first*deltaT/tr*(1.+0.5*deltaT/tr*pT/pmag);
00145         if(mass<0.) continue;
00146         mass = sqrt(mass);
00147         filled = true;
00148         _hist_mass->fill(mass,weight);
00149         if(mass>90. ) {
00150           _count_90 ->fill(0.5,weight);
00151           if(mass>110.) {
00152             _count_110->fill(0.5,weight);
00153             if(mass>120.) {
00154               _count_120->fill(0.5,weight);
00155               if(mass>130.) {
00156                 _count_130->fill(0.5,weight);
00157               }
00158             }
00159           }
00160         }
00161       }
00162       if(!filled) vetoEvent;
00163       // number passing beta cut
00164       _count_beta->fill(0.5,weight);
00165     }
00166 
00167     //@}
00168 
00169     void finalize() {
00170       double fact = crossSection()/sumOfWeights()*37;
00171       MSG_WARNING("testing " << crossSection() << " " << sumOfWeights() << " " << fact);
00172       scale(_hist_beta,fact);
00173       scale(_hist_time,fact);
00174       scale(_hist_mass,fact);
00175       scale( _count_trigger, fact);
00176       scale( _count_event, fact);
00177       scale( _count_quality, fact);
00178       scale( _count_beta, fact);
00179       scale( _count_90, fact);
00180       scale( _count_110, fact);
00181       scale( _count_120, fact);
00182       scale( _count_130, fact);
00183     }
00184 
00185   private:
00186 
00187     /// @name Histograms
00188     //@{
00189     Histo1DPtr _hist_beta;
00190     Histo1DPtr _hist_time;
00191     Histo1DPtr _hist_mass;
00192     Histo1DPtr _count_trigger;
00193     Histo1DPtr _count_event;
00194     Histo1DPtr _count_quality;
00195     Histo1DPtr _count_beta;
00196     Histo1DPtr _count_90;
00197     Histo1DPtr _count_110;
00198     Histo1DPtr _count_120;
00199     Histo1DPtr _count_130;
00200     //@}
00201 
00202   };
00203 
00204   // The hook for the plugin system
00205   DECLARE_RIVET_PLUGIN(ATLAS_2011_S9108483);
00206 
00207 
00208 }