CMS 3D CMS Logo

ME0PreRecoGaussianModel.cc
Go to the documentation of this file.
5 
8 
9 #include "CLHEP/Random/RandFlat.h"
10 #include "CLHEP/Random/RandGaussQ.h"
11 #include "CLHEP/Random/RandPoissonQ.h"
12 
13 #include <cmath>
14 #include <utility>
15 #include <map>
16 
17 
18 const int bxwidth = 25; // [ns]
19 
21  ME0DigiPreRecoModel(config),
22  sigma_t(config.getParameter<double>("timeResolution")),
23  sigma_u(config.getParameter<double>("phiResolution")),
24  sigma_v(config.getParameter<double>("etaResolution")),
25  error_u(config.getParameter<double>("phiError")),
26  error_v(config.getParameter<double>("etaError")),
27  gaussianSmearing_(config.getParameter<bool>("gaussianSmearing")),
28  constPhiSmearing_(config.getParameter<bool>("constantPhiSpatialResolution")),
29  corr(config.getParameter<bool>("useCorrelation")),
30  etaproj(config.getParameter<bool>("useEtaProjectiveGEO")),
31  digitizeOnlyMuons_(config.getParameter<bool>("digitizeOnlyMuons")),
32  averageEfficiency_(config.getParameter<double>("averageEfficiency")),
33  // simulateIntrinsicNoise_(config.getParameter<bool>("simulateIntrinsicNoise")),
34  // averageNoiseRate_(config.getParameter<double>("averageNoiseRate")),
35  simulateElectronBkg_(config.getParameter<bool>("simulateElectronBkg")),
36  simulateNeutralBkg_(config.getParameter<bool>("simulateNeutralBkg")),
37  minBunch_(config.getParameter<int>("minBunch")),
38  maxBunch_(config.getParameter<int>("maxBunch")),
39  instLumi_(config.getParameter<double>("instLumi")),
40  rateFact_(config.getParameter<double>("rateFact")),
41  referenceInstLumi_(config.getParameter<double>("referenceInstLumi"))
42 {
43  // polynomial parametrisation of neutral (n+g) and electron background
44  // This is the background for an Instantaneous Luminosity of L = 5E34 cm^-2 s^-1
45  neuBkg.push_back(0.00386257);
46  neuBkg.push_back(6344.65);
47  neuBkg.push_back(16627700);
48  neuBkg.push_back(-102098);
49 
50  eleBkg.push_back(0.00171409);
51  eleBkg.push_back(4900.56);
52  eleBkg.push_back(710909);
53  eleBkg.push_back(-4327.25);
54 }
55 
57 {
58 }
59 
60 void ME0PreRecoGaussianModel::simulateSignal(const ME0EtaPartition* roll, const edm::PSimHitContainer& simHits, CLHEP::HepRandomEngine* engine)
61 {
62 for (const auto & hit: simHits)
63 {
64  // Digitize only Muons?
65  if (std::abs(hit.particleType()) != 13 && digitizeOnlyMuons_) continue;
66  // Digitize only in [minBunch,maxBunch] window
67  // window is: [(2n+1)*bxw/2, (2n+3)*bxw/2], n = [minBunch, maxBunch]
68  if(hit.timeOfFlight() < (2*minBunch_+1)*bxwidth*1.0/2 || hit.timeOfFlight() > (2*maxBunch_+3)*bxwidth*1.0/2) continue;
69  // is GEM efficient?
70  if (CLHEP::RandFlat::shoot(engine) > averageEfficiency_) continue;
71  // create digi
72  auto entry = hit.entryPoint();
73  double x=0.0, y=0.0;
74 
75  double sigma_u_new = sigma_u;
76  if(constPhiSmearing_) sigma_u_new = correctSigmaU(roll, entry.y());
77 
78  if(gaussianSmearing_) { // Gaussian Smearing
79  x=CLHEP::RandGaussQ::shoot(engine, entry.x(), sigma_u_new);
80  y=CLHEP::RandGaussQ::shoot(engine, entry.y(), sigma_v);
81  }
82  else { // Uniform Smearing ... use the sigmas as boundaries
83  x=entry.x()+(CLHEP::RandFlat::shoot(engine)-0.5)*sigma_u_new;
84  y=entry.y()+(CLHEP::RandFlat::shoot(engine)-0.5)*sigma_v;
85  }
86  double ex=sigma_u_new;
87  double ey=sigma_v;
88  double corr=0.;
89  double tof=CLHEP::RandGaussQ::shoot(engine, hit.timeOfFlight(), sigma_t);
90  int pdgid = hit.particleType();
91  if (ex == 0) ex = error_u;//errors cannot be zero
92  if (ey == 0) ey = error_v;
93 
94  int evtId = hit.eventId().event();
95  int bx = hit.eventId().bunchCrossing();
96  int procType = hit.processType();
97  int res = 1;
98  if(!(evtId == 0 && bx == 0 && procType == 0)) res = 2;
99 
100  digi_.emplace(x,y,ex,ey,corr,tof,pdgid,res);
101 
102  edm::LogVerbatim("ME0PreRecoGaussianModel") << "[ME0PreRecoDigi :: simulateSignal] :: simhit in "<<roll->id()<<" at loc x = "<<std::setw(8)<<entry.x()<<" [cm]"
103  << " loc y = "<<std::setw(8)<<entry.y()<<" [cm] time = "<<std::setw(8)<<hit.timeOfFlight()<<" [ns] pdgid = "<<std::showpos<<std::setw(4)<<pdgid;
104  edm::LogVerbatim("ME0PreRecoGaussianModel") << "[ME0PreRecoDigi :: simulateSignal] :: digi in "<<roll->id()<<" at loc x = "<<std::setw(8)<<x<<" [cm] loc y = "<<std::setw(8)<<y<<" [cm]"
105  <<" time = "<<std::setw(8)<<tof<<" [ns]";
106  edm::LogVerbatim("ME0PreRecoGaussianModel") << "[ME0PreRecoDigi :: simulateSignal] :: digi in "<<roll->id()<<" with DX = "<<std::setw(8)<<(entry.x()-x)<<" [cm]"
107  <<" DY = "<<std::setw(8)<<(entry.y()-y)<<" [cm] DT = "<<std::setw(8)<<(hit.timeOfFlight()-tof)<<" [ns]";
108 
109 }
110 }
111 
112 void ME0PreRecoGaussianModel::simulateNoise(const ME0EtaPartition* roll, CLHEP::HepRandomEngine* engine)
113 {
114  double trArea(0.0);
115  const ME0DetId me0Id(roll->id());
116 
117  // Extract detailed information from the Strip Topology:
118  // base_bottom, base_top, height, strips, pads
119  // note that (0,0) is in the middle of the roll ==> all param are at all half length
120  if (me0Id.region() == 0) { throw cms::Exception("Geometry") << "Asking TrapezoidalStripTopology from a ME0 will fail"; } // not sure we really need this
121  const TrapezoidalStripTopology* top_(dynamic_cast<const TrapezoidalStripTopology*>(&(roll->topology())));
122 
123  auto& parameters(roll->specs()->parameters());
124  double bottomLength(parameters[0]); bottomLength = 2*bottomLength; // bottom is largest length, so furtest away from beamline
125  double topLength(parameters[1]); topLength = 2*topLength; // top is shortest length, so closest to beamline
126  double height(parameters[2]); height = 2*height;
127  double myTanPhi = (topLength - bottomLength) / (height * 2);
128  double rollRadius = top_->radius();
129  trArea = height * (topLength + bottomLength) / 2.0;
130 
131  // Divide the detector area in different strips
132  // take smearing in y-coord as height for each strip
133  double initialHeight = sigma_v;
134  if(sigma_v < 1.0) initialHeight = 1.0;
135  double heightIt = initialHeight;
136  int heightbins = height/heightIt; // round down
137 
138  edm::LogVerbatim("ME0PreRecoGaussianModelNoise") << "[ME0PreRecoDigi :: sNoise]["<<roll->id().rawId()<<"] :: roll with id = "<<roll->id();
139  edm::LogVerbatim("ME0PreRecoGaussianModelNoise") << "[ME0PreRecoDigi :: sNoise]["<<roll->id().rawId()<<"] :: extracting parameters from the TrapezoidalStripTopology";
140  edm::LogVerbatim("ME0PreRecoGaussianModelNoise") << "[ME0PreRecoDigi :: sNoise]["<<roll->id().rawId()<<"] :: bottom = "<<bottomLength<<" [cm] top = "<<topLength<<" [cm] height = "<<height<<" [cm]"
141  <<" area = "<<trArea<<" [cm^2] Rmid = "<<rollRadius<<" [cm] => Rmin = "<<rollRadius-height*1.0/2.0<<" [cm] Rmax = "<<rollRadius+height*1.0/2.0<<" [cm]";
142  edm::LogVerbatim("ME0PreRecoGaussianModelNoise") << "[ME0PreRecoDigi :: sNoise]["<<roll->id().rawId()<<"] :: heightbins = "<<heightbins;
143 
144  for(int hx=0; hx<heightbins; ++hx) {
145  double bottomIt = bottomLength + hx *2*tan(10./180*3.14)*heightIt;
146  double topIt = bottomLength + (hx+1)*2*tan(10./180*3.14)*heightIt;
147  if(hx==heightbins-1) {
148  topIt = topLength; // last bin ... make strip a bit larger to cover entire roll
149  heightIt = height-hx*heightIt;
150  }
151  double areaIt = heightIt*(bottomIt+topIt)*1.0/2;
152 
153  edm::LogVerbatim("ME0PreRecoGaussianModelNoise") << "[ME0PreRecoDigi :: sNoise]["<<roll->id().rawId()<<"] :: height = "<<std::setw(12)<<heightIt<<" [cm] bottom = "<<std::setw(12)<<bottomIt<<" [cm]"
154  << " top = "<<std::setw(12)<<topIt<<" [cm] area = "<<std::setw(12)<<areaIt<<" [cm^2] || sin(10) = "<<sin(10./180*3.14);
155 
156  double myRandY = CLHEP::RandFlat::shoot(engine);
157  double y0_rand = (hx+myRandY)*heightIt; // Y coord, measured from the bottom of the roll
158  if(hx==heightbins-1) y0_rand = hx*initialHeight + myRandY*heightIt;
159  double yy_rand = (y0_rand-height*1.0/2); // Y coord, measured from the middle of the roll, which is the Y coord in Local Coords
160  double yy_glob = rollRadius + yy_rand; // R coord in Global Coords
161  // max length in x for given y coordinate (cfr trapezoidal eta partition)
162  const float rSqrtR = yy_glob * sqrt(yy_glob);
163  double xMax = topLength/2.0 - (height/2.0 - yy_rand) * myTanPhi;
164 
165  double sigma_u_new = sigma_u;
166  if(constPhiSmearing_) sigma_u_new = correctSigmaU(roll, yy_rand);
167 
168 
169  // 1) Intrinsic Noise ... Not implemented right now
170  // ------------------------------------------------
171  // if (simulateIntrinsicNoise_)
172  // {
173  // }
174 
175  // 2) Background Noise
176  // ----------------------------
177 
178  // 2a) electron background
179  // -----------------------
180  if (simulateElectronBkg_) {
181  // Extract / Calculate the Average Electron Rate
182  // for the given global Y coord from Parametrization
183  double averageElectronRatePerRoll = eleBkg[0] * rSqrtR* std::exp( eleBkg[1]/rSqrtR) + eleBkg[2]/rSqrtR + eleBkg[3]/(sqrt(yy_glob));
184  // Scale up/down for desired instantaneous lumi (reference is 5E34, double from config is in units of 1E34)
185  averageElectronRatePerRoll *= instLumi_*rateFact_*1.0/referenceInstLumi_;
186 
187  // Rate [Hz/cm^2] * Nbx * 25*10^-9 [s] * Area [cm] = # hits in this roll in this bx
188  const double averageElecRate(averageElectronRatePerRoll * (maxBunch_-minBunch_+1)*(bxwidth*1.0e-9) * areaIt);
189 
190  edm::LogVerbatim("ME0PreRecoGaussianModelNoise") << "[ME0PreRecoDigi :: elebkg]["<<roll->id().rawId()<<"]" /* "] :: BX = "<<std::showpos<<bx*/
191  << " evaluation of Background Hit Rate at this coord :: "<<std::setw(12)<<averageElectronRatePerRoll<<" [Hz/cm^2]"
192  << " x 9 x 25*10^-9 [s] x Area (of strip = "<<std::setw(12)<<areaIt<<" [cm^2]) ==> "<<std::setw(12)<<averageElecRate<<" [hits]";
193 
194  bool ele_eff = (CLHEP::RandFlat::shoot(engine)<averageElecRate)?true:false;
195 
196  edm::LogVerbatim("ME0PreRecoGaussianModelNoise") << "[ME0PreRecoDigi :: elebkg]["<<roll->id().rawId()<<"] :: myRandY = "<<std::setw(12)<<myRandY<<" => local y = "<<std::setw(12)<<yy_rand<<" [cm]"
197  <<" => global y (global R) = "<<std::setw(12)<<yy_glob<<" [cm] || Probability = "<<std::setw(12)<<averageElecRate
198  <<" => efficient? "<<ele_eff<<std::endl;
199 
200  if(ele_eff) {
201  //calculate xx_rand at a given yy_rand
202  double myRandX = CLHEP::RandFlat::shoot(engine);
203  double xx_rand = 2 * xMax * (myRandX - 0.5);
204  double ex = sigma_u_new;
205  double ey = sigma_v;
206  double corr = 0.;
207  // extract random BX
208  double myrandBX = CLHEP::RandFlat::shoot(engine);
209  int bx = int((maxBunch_-minBunch_+1)*myrandBX)+minBunch_;
210  // extract random time in this BX
211  double myrandT = CLHEP::RandFlat::shoot(engine);
212  double minBXtime = (bx-0.5)*bxwidth; // double maxBXtime = (bx+0.5)*bxwidth;
213  double time = myrandT*bxwidth+minBXtime;
214  double myrandP = CLHEP::RandFlat::shoot(engine);
215  int pdgid = 0;
216  if (myrandP <= 0.5) pdgid = -11; // electron
217  else pdgid = 11; // positron
218  if (ex == 0) ex = error_u;//errors cannot be zero
219  if (ey == 0) ey = error_v;
220 
221  digi_.emplace(xx_rand, yy_rand, ex, ey, corr, time, pdgid, 0);
222 
223  edm::LogVerbatim("ME0PreRecoGaussianModelNoise") << "[ME0PreRecoDigi :: elebkg]["<<roll->id().rawId()
224  <<"] =====> electron hit in "<<roll->id()
225  <<" pdgid = "<<pdgid<<" bx = "<<bx
226  <<" ==> digitized"
227  <<" at loc x = "<<xx_rand<<" loc y = "<<yy_rand
228  <<" time = "<<time<<" [ns]";
229  }
230  } // end if electron bkg
231 
232  // 2b) neutral (n+g) background
233  // ----------------------------
234  if (simulateNeutralBkg_) {
235  // Extract / Calculate the Average Neutral Rate
236  // for the given global Y coord from Parametrization
237  double averageNeutralRatePerRoll = neuBkg[0] * yy_glob* std::exp( neuBkg[1]/rSqrtR) +
238  neuBkg[2]/rSqrtR + neuBkg[3]/(sqrt(yy_glob));
239  // Scale up/down for desired instantaneous lumi (reference is 5E34, double from config is in units of 1E34)
240  averageNeutralRatePerRoll *= instLumi_*rateFact_*1.0/referenceInstLumi_;
241 
242  // Rate [Hz/cm^2] * Nbx * 25*10^-9 [s] * Area [cm] = # hits in this roll
243  const double averageNeutrRate(averageNeutralRatePerRoll * (maxBunch_-minBunch_+1)*(bxwidth*1.0e-9) * areaIt);
244 
245  edm::LogVerbatim("ME0PreRecoGaussianModelNoise") << "[ME0PreRecoDigi :: neubkg]["<<roll->id().rawId()<<"]" /* "] :: BX = "<<std::showpos<<bx*/
246  << " evaluation of Background Hit Rate at this coord :: "<<std::setw(12)<<averageNeutralRatePerRoll<<" [Hz/cm^2]"
247  << " x 9 x 25*10^-9 [s] x Area (of strip = "<<std::setw(12)<<areaIt<<" [cm^2]) ==> "<<std::setw(12)<<averageNeutrRate<<" [hits]";
248 
249  bool neu_eff = (CLHEP::RandFlat::shoot(engine)<averageNeutrRate)?true:false;
250 
251  edm::LogVerbatim("ME0PreRecoGaussianModelNoise") << "[ME0PreRecoDigi :: neubkg]["<<roll->id().rawId()<<"] :: myRandY = "<<std::setw(12)<<myRandY<<" => local y = "<<std::setw(12)<<yy_rand<<" [cm]"
252  <<" => global y (global R) = "<<std::setw(12)<<yy_glob<<" [cm] || Probability = "<<std::setw(12)<<averageNeutrRate
253  <<" => efficient? "<<neu_eff<<std::endl;
254 
255  if(neu_eff) {
256  //calculate xx_rand at a given yy_rand
257  double myRandX = CLHEP::RandFlat::shoot(engine);
258  double xx_rand = 2 * xMax * (myRandX - 0.5);
259  double ex = sigma_u_new;
260  double ey = sigma_v;
261  double corr = 0.;
262  // extract random BX
263  double myrandBX= CLHEP::RandFlat::shoot(engine);
264  int bx = int((maxBunch_-minBunch_+1)*myrandBX)+minBunch_;
265  // extract random time in this BX
266  double myrandT = CLHEP::RandFlat::shoot(engine);
267  double minBXtime = (bx-0.5)*bxwidth;
268  double time = myrandT*bxwidth+minBXtime;
269  int pdgid = 0;
270  double myrandP = CLHEP::RandFlat::shoot(engine);
271  if (myrandP <= 0.08) pdgid = 2112; // neutrons: GEM sensitivity for neutrons: 0.08%
272  else pdgid = 22; // photons: GEM sensitivity for photons: 1.04% ==> neutron fraction = (0.08 / 1.04) = 0.077 = 0.08
273  if (ex == 0) ex = error_u;//errors cannot be zero
274  if (ey == 0) ey = error_v;
275 
276  digi_.emplace(xx_rand, yy_rand, ex, ey, corr, time, pdgid, 0);
277 
278  edm::LogVerbatim("ME0PreRecoGaussianModelNoise") << "[ME0PreRecoDigi :: neubkg]["<<roll->id().rawId()
279  <<"] ======> neutral hit in "<<roll->id()
280  <<" pdgid = "<<pdgid<<" bx = "<<bx
281  <<" ==> digitized"
282  <<" at loc x = "<<xx_rand<<" loc y = "<<yy_rand
283  <<" time = "<<time<<" [ns]";
284  }
285 
286  } // end if neutral bkg
287  } // end loop over strips (= pseudo rolls)
288 }
289 
291  const TrapezoidalStripTopology* top_(dynamic_cast<const TrapezoidalStripTopology*>(&(roll->topology())));
292  auto& parameters(roll->specs()->parameters());
293  double height(parameters[2]); // height = height from Center of Roll
294  double rollRadius = top_->radius(); // rollRadius = Radius at Center of Roll
295  double Rmax = rollRadius+height; // MaxRadius = Radius at top of Roll
296  double Rx = rollRadius+y; // y in [-height,+height]
297  double sigma_u_new = Rx/Rmax*sigma_u;
298  return sigma_u_new;
299 }
const ME0EtaPartitionSpecs * specs() const
std::vector< double > neuBkg
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:50
const ME0Specs & parameters() const
Definition: config.py:1
Definition: Electron.h:6
double correctSigmaU(const ME0EtaPartition *, double)
const int bxwidth
T sqrt(T t)
Definition: SSEVec.h:18
ME0DetId id() const
Tan< T >::type tan(const T &t)
Definition: Tan.h:22
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
JetCorrectorParameters corr
Definition: classes.h:5
void simulateSignal(const ME0EtaPartition *, const edm::PSimHitContainer &, CLHEP::HepRandomEngine *) override
std::set< ME0DigiPreReco > digi_
void simulateNoise(const ME0EtaPartition *, CLHEP::HepRandomEngine *) override
ME0PreRecoGaussianModel(const edm::ParameterSet &)
const double Rmax[kNumberCalorimeter]
std::vector< PSimHit > PSimHitContainer
std::vector< double > eleBkg
const Topology & topology() const override