ATLAS_2012_I1084540.cc
Go to the documentation of this file.
00001 // -*- C++ -*- 00002 /** 00003 * @name ATLAS Diffractive Gaps Rivet Analysis 00004 * @author Tim Martin, tim.martin@cern.ch 00005 * @version 1.0 00006 * @date 16/01/2012 00007 * @see http://arxiv.org/abs/1201.2808 00008 * @note pp, sqrt(s) = 7 TeV 00009 * @note Rapidity gap finding algorithm designed to compliment 00010 * the ATLAS detector acceptance. Forward rapidity gap sizes 00011 * are calculated for each event, considering all stable 00012 * particles above pT cut values 200, 400, 600 and 800 MeV in 00013 * turn. A forward rapidity gap is defined to be the largest 00014 * continuous region stretching inward from either edge of the 00015 * detector at eta = |4.9| which contains zero particles above 00016 * pT Cut. Soft diffractive topologies are isolated at large 00017 * gap sizes. 00018 * 00019 */ 00020 #include "Rivet/Analysis.hh" 00021 #include "Rivet/RivetYODA.hh" 00022 #include "Rivet/Tools/Logging.hh" 00023 #include "Rivet/Projections/FinalState.hh" 00024 00025 namespace Rivet { 00026 00027 00028 class ATLAS_2012_I1084540 : public Analysis { 00029 public: 00030 00031 ATLAS_2012_I1084540() : Analysis("ATLAS_2012_I1084540"), _etaBins(49), _etaMax(4.9) { 00032 } 00033 00034 00035 /// @name Analysis methods 00036 //@{ 00037 /// Book histograms and initialise projections before the run 00038 void init() { 00039 //All final states. Rapidity range = ATLAS calorimetry. Lowest pT cut = 200 MeV. 00040 const FinalState cnfs2(-_etaMax, _etaMax, 0.2 * GeV); 00041 const FinalState cnfs4(-_etaMax, _etaMax, 0.4 * GeV); 00042 const FinalState cnfs6(-_etaMax, _etaMax, 0.6 * GeV); 00043 const FinalState cnfs8(-_etaMax, _etaMax, 0.8 * GeV); 00044 addProjection(cnfs2, "CNFS2"); 00045 addProjection(cnfs4, "CNFS4"); 00046 addProjection(cnfs6, "CNFS6"); 00047 addProjection(cnfs8, "CNFS8"); 00048 00049 _etaBinSize = (2. * _etaMax)/(double)_etaBins; 00050 00051 //Book histogram 00052 _h_DeltaEtaF_200 = bookHisto1D(1, 1, 1); 00053 _h_DeltaEtaF_400 = bookHisto1D(2, 1, 1); 00054 _h_DeltaEtaF_600 = bookHisto1D(3, 1, 1); 00055 _h_DeltaEtaF_800 = bookHisto1D(4, 1, 1); 00056 } 00057 00058 private: 00059 void fillMap(const FinalState& fs, bool* energyMap, double pTcut) { 00060 // Fill true/false array by iterating over particles and compare their 00061 // pT with pTcut 00062 foreach (const Particle& p, fs.particlesByEta()) { 00063 int checkBin = -1; 00064 double checkEta = -_etaMax; 00065 while (1) { 00066 checkEta += _etaBinSize; 00067 ++checkBin; 00068 if (p.momentum().eta() < checkEta) { 00069 energyMap[checkBin] = (p.momentum().pT() > pTcut * GeV); 00070 break; 00071 } 00072 } 00073 } 00074 } 00075 00076 public: 00077 /// Perform the per-event analysis 00078 void analyze(const Event& event) { 00079 static unsigned int event_count = 0; 00080 ++event_count; 00081 const double weight = event.weight(); 00082 const FinalState& fs2 = applyProjection<FinalState>(event, "CNFS2"); 00083 const FinalState& fs4 = applyProjection<FinalState>(event, "CNFS4"); 00084 const FinalState& fs6 = applyProjection<FinalState>(event, "CNFS6"); 00085 const FinalState& fs8 = applyProjection<FinalState>(event, "CNFS8"); 00086 00087 // Set up Yes/No arrays for energy in each eta bin at each pT cut 00088 bool* energyMap_200 = new bool[_etaBins]; 00089 bool* energyMap_400 = new bool[_etaBins]; 00090 bool* energyMap_600 = new bool[_etaBins]; 00091 bool* energyMap_800 = new bool[_etaBins]; 00092 for (int i = 0; i < _etaBins; ++i) { 00093 energyMap_200[i] = false; 00094 energyMap_400[i] = false; 00095 energyMap_600[i] = false; 00096 energyMap_800[i] = false; 00097 } 00098 00099 // Veto bins based on final state particles > Cut (Where Cut = 200 - 800 MeV pT) 00100 fillMap(fs2, energyMap_200, 0.2); 00101 fillMap(fs4, energyMap_400, 0.4); 00102 fillMap(fs6, energyMap_600, 0.6); 00103 fillMap(fs8, energyMap_800, 0.8); 00104 00105 // Apply gap finding algorithm 00106 // Detector layout follows... 00107 // -Eta [Proton --- DetectorCSide --- DetectorBarrel --- DetectorASide --- Proton] +Eta 00108 bool gapDirectionAt200 = false; //False is gap on C size, True is gap on A side. 00109 double largestEdgeGap_200 = 0.; 00110 double largestEdgeGap_400 = 0.; 00111 double largestEdgeGap_600 = 0.; 00112 double largestEdgeGap_800 = 0.; 00113 00114 for (int E = 200; E <= 800; E += 200) { 00115 double EdgeGapSizeA = -1, EdgeGapSizeC = -1; 00116 bool* energyMap = 0; 00117 switch (E) { 00118 case 200: energyMap = energyMap_200; break; 00119 case 400: energyMap = energyMap_400; break; 00120 case 600: energyMap = energyMap_600; break; 00121 case 800: energyMap = energyMap_800; break; 00122 } 00123 00124 // Look left to right 00125 for (int a = 0; a < _etaBins; ++a) { 00126 if (energyMap[a] == true) { 00127 EdgeGapSizeA = (_etaBinSize * a); 00128 break; 00129 } 00130 } 00131 00132 // And look right to left 00133 for (int c = _etaBins-1; c >= 0; --c) { 00134 if (energyMap[c] == true) { 00135 EdgeGapSizeC = (2 * _etaMax) - (_etaBinSize * (c+1)); 00136 if (fuzzyEquals(EdgeGapSizeC, 4.47035e-08)) EdgeGapSizeC = 0.0; 00137 break; 00138 } 00139 } 00140 // Put your hands on your hips 00141 00142 // Find the largest gap 00143 double largestEdgeGap = 0.; 00144 if (E == 200) { 00145 // If the 200 MeV pass, take the biggest of the two gaps. Make note of which side for higher pT cuts. 00146 largestEdgeGap = std::max(EdgeGapSizeA,EdgeGapSizeC); 00147 gapDirectionAt200 = (EdgeGapSizeA > EdgeGapSizeC); 00148 } else { 00149 // Use the direction from 200 MeV pass, most accurate measure of which side gap is on. 00150 if (gapDirectionAt200) { 00151 largestEdgeGap = EdgeGapSizeA; 00152 } 00153 else largestEdgeGap = EdgeGapSizeC; 00154 } 00155 00156 // Check case of empty detector 00157 if (largestEdgeGap < 0.0) largestEdgeGap = 2.0 * _etaMax; 00158 00159 // Fill bin centre 00160 switch (E) { 00161 case 200: _h_DeltaEtaF_200->fill(largestEdgeGap + _etaBinSize/2., weight); break; 00162 case 400: _h_DeltaEtaF_400->fill(largestEdgeGap + _etaBinSize/2., weight); break; 00163 case 600: _h_DeltaEtaF_600->fill(largestEdgeGap + _etaBinSize/2., weight); break; 00164 case 800: _h_DeltaEtaF_800->fill(largestEdgeGap + _etaBinSize/2., weight); break; 00165 } 00166 00167 if (E == 200) largestEdgeGap_200 = largestEdgeGap; 00168 if (E == 400) largestEdgeGap_400 = largestEdgeGap; 00169 if (E == 600) largestEdgeGap_600 = largestEdgeGap; 00170 if (E == 800) largestEdgeGap_800 = largestEdgeGap; 00171 } 00172 00173 // Algorithm result every 1000 events 00174 if (event_count % 1000 == 0) { 00175 for (int E = 200; E <= 800; E += 200) { 00176 bool* energyMap = 0; 00177 double largestEdgeGap = 0; 00178 switch (E) { 00179 case 200: energyMap = energyMap_200; largestEdgeGap = largestEdgeGap_200; break; 00180 case 400: energyMap = energyMap_400; largestEdgeGap = largestEdgeGap_400; break; 00181 case 600: energyMap = energyMap_600; largestEdgeGap = largestEdgeGap_600; break; 00182 case 800: energyMap = energyMap_800; largestEdgeGap = largestEdgeGap_800; break; 00183 } 00184 MSG_DEBUG("Largest Forward Gap at pT Cut " << E << " MeV=" << largestEdgeGap 00185 << " eta, NFinalState pT > 200 in ATLAS acceptance:" << fs2.particles().size()); 00186 std::string hitPattern = "Detector HitPattern=-4.9["; 00187 for (int a = 0; a < _etaBins; ++a) { 00188 if (energyMap[a] == true) hitPattern += "X"; 00189 else hitPattern += "_"; 00190 } 00191 hitPattern += "]4.9"; 00192 MSG_DEBUG(hitPattern); 00193 std::string gapArrow = " "; 00194 if (!gapDirectionAt200) { 00195 int drawSpaces = (int)(_etaBins - (largestEdgeGap/_etaBinSize) + 0.5); 00196 for (int i = 0; i < drawSpaces; ++i) gapArrow += " "; 00197 } 00198 int drawArrows = (int)((largestEdgeGap/_etaBinSize) + 0.5); 00199 for (int i = 0; i < drawArrows; ++i) gapArrow += "^"; 00200 MSG_DEBUG(gapArrow); 00201 } 00202 } 00203 00204 delete[] energyMap_200; 00205 delete[] energyMap_400; 00206 delete[] energyMap_600; 00207 delete[] energyMap_800; 00208 } 00209 00210 /// Normalise histograms after the run, Scale to cross section 00211 void finalize() { 00212 MSG_DEBUG("Cross Section=" << crossSection() / millibarn << "mb, SumOfWeights=" << sumOfWeights()); 00213 scale(_h_DeltaEtaF_200, (crossSection() / millibarn)/sumOfWeights()); 00214 scale(_h_DeltaEtaF_400, (crossSection() / millibarn)/sumOfWeights()); 00215 scale(_h_DeltaEtaF_600, (crossSection() / millibarn)/sumOfWeights()); 00216 scale(_h_DeltaEtaF_800, (crossSection() / millibarn)/sumOfWeights()); 00217 } 00218 //@} 00219 00220 private: 00221 /// @name Histograms 00222 //@{ 00223 Histo1DPtr _h_DeltaEtaF_200; 00224 Histo1DPtr _h_DeltaEtaF_400; 00225 Histo1DPtr _h_DeltaEtaF_600; 00226 Histo1DPtr _h_DeltaEtaF_800; 00227 //@} 00228 /// @name Private variables 00229 //@{ 00230 int _etaBins; 00231 double _etaMax; 00232 double _etaBinSize; 00233 //@} 00234 }; 00235 00236 // The hook for the plugin system 00237 DECLARE_RIVET_PLUGIN(ATLAS_2012_I1084540); 00238 00239 } Generated on Fri Dec 21 2012 15:03:39 for The Rivet MC analysis system by ![]() |