CMS 3D CMS Logo

GEMSimpleModel.cc
Go to the documentation of this file.
6 #include "CLHEP/Random/RandFlat.h"
7 #include "CLHEP/Random/RandPoissonQ.h"
8 #include "CLHEP/Random/RandGaussQ.h"
9 #include <cmath>
10 #include <utility>
11 #include <map>
12 #include "TMath.h" /* exp */
13 
14 namespace
15 {
16  // "magic" parameter for cosmics
17  const double COSMIC_PAR(37.62);
18 }
19 
21 GEMDigiModel(config)
22 , averageEfficiency_(config.getParameter<double> ("averageEfficiency"))
23 , averageShapingTime_(config.getParameter<double> ("averageShapingTime"))
24 , timeResolution_(config.getParameter<double> ("timeResolution"))
25 , timeJitter_(config.getParameter<double> ("timeJitter"))
26 , averageNoiseRate_(config.getParameter<double> ("averageNoiseRate"))
27 , signalPropagationSpeed_(config.getParameter<double> ("signalPropagationSpeed"))
28 , cosmics_(config.getParameter<bool> ("cosmics"))
29 , bxwidth_(config.getParameter<int> ("bxwidth"))
30 , minBunch_(config.getParameter<int> ("minBunch"))
31 , maxBunch_(config.getParameter<int> ("maxBunch"))
32 , digitizeOnlyMuons_(config.getParameter<bool> ("digitizeOnlyMuons"))
33 , doBkgNoise_(config.getParameter<bool> ("doBkgNoise"))
34 , doNoiseCLS_(config.getParameter<bool> ("doNoiseCLS"))
35 , fixedRollRadius_(config.getParameter<bool> ("fixedRollRadius"))
36 , simulateElectronBkg_(config.getParameter<bool> ("simulateElectronBkg"))
37 , simulateLowNeutralRate_(config.getParameter<bool>("simulateLowNeutralRate"))
38 , instLumi_(config.getParameter<double>("instLumi"))
39 , rateFact_(config.getParameter<double>("rateFact"))
40 {
41 //initialise parameters from the fit:
42 //params for pol3 model of electron bkg for GE1/1:
43  GE11ElecBkgParam0 = 3402.63;
44  GE11ElecBkgParam1 = -42.9979;
45  GE11ElecBkgParam2 = 0.188475;
46  GE11ElecBkgParam3 = -0.0002822;
47 //params for expo model of electron bkg for GE2/1:
48  constElecGE21 = 9.74156e+02;
49  slopeElecGE21 = -1.18398e-02;
50 //Neutral Bkg
51 //Low Rate model L=10^{34}cm^{-2}s^{-1}
52 //const and slope for the expo model of neutral bkg for GE1/1:
53  constNeuGE11 = 807.;
54  slopeNeuGE11 = -0.01443;
55 //params for the simple pol5 model of neutral bkg for GE2/1:
56  GE21NeuBkgParam0 = 2954.04;
57  GE21NeuBkgParam1 = -58.7558;
58  GE21NeuBkgParam2 = 0.473481;
59  GE21NeuBkgParam3 = -0.00188292;
60  GE21NeuBkgParam4 = 3.67041e-06;
61  GE21NeuBkgParam5 = -2.80261e-09;
62 //High Rate model L=5x10^{34}cm^{-2}s^{-1}
63 //params for expo model of neutral bkg for GE1/1:
64  constNeuGE11_highRate = 1.02603e+04;
65  slopeNeuGE11_highRate = -1.62806e-02;
66 //params for pol5 model of neutral bkg for GE2/1:
67  GE21ModNeuBkgParam0 = 21583.2;
68  GE21ModNeuBkgParam1 = -476.59;
69  GE21ModNeuBkgParam2 = 4.24037;
70  GE21ModNeuBkgParam3 = -0.0185558;
71  GE21ModNeuBkgParam4 = 3.97809e-05;
72  GE21ModNeuBkgParam5 = -3.34575e-08;
73 }
74 
76 {
77 }
78 
80 {
81  return;
82 }
83 
84 void GEMSimpleModel::simulateSignal(const GEMEtaPartition* roll, const edm::PSimHitContainer& simHits, CLHEP::HepRandomEngine* engine)
85 {
87  detectorHitMap_.clear();
91  bool digiMuon = false;
92  bool digiElec = false;
93  for (edm::PSimHitContainer::const_iterator hit = simHits.begin(); hit != simHits.end(); ++hit)
94  {
95  if (std::abs(hit->particleType()) != 13 && digitizeOnlyMuons_)
96  continue;
97  double elecEff = 0.;
98  double partMom = hit->pabs();
99  double checkMuonEff = CLHEP::RandFlat::shoot(engine, 0., 1.);
100  double checkElecEff = CLHEP::RandFlat::shoot(engine, 0., 1.);
101  if (std::abs(hit->particleType()) == 13 && checkMuonEff < averageEfficiency_)
102  digiMuon = true;
103  if (std::abs(hit->particleType()) != 13) //consider all non muon particles with gem efficiency to electrons
104  {
105  if (partMom <= 1.95e-03)
106  elecEff = 1.7e-05 * TMath::Exp(2.1 * partMom * 1000.);
107  if (partMom > 1.95e-03 && partMom < 10.e-03)
108  elecEff = 1.34 * log(7.96e-01 * partMom * 1000. - 5.75e-01)
109  / (1.34 + log(7.96e-01 * partMom * 1000. - 5.75e-01));
110  if (partMom > 10.e-03)
111  elecEff = 1.;
112  if (checkElecEff < elecEff)
113  digiElec = true;
114  }
115  if (!(digiMuon || digiElec))
116  continue;
117  const int bx(getSimHitBx(&(*hit), engine));
118  const std::vector<std::pair<int, int> > cluster(simulateClustering(roll, &(*hit), bx, engine));
119  for (auto & digi : cluster)
120  {
122  strips_.insert(digi);
123  }
124  }
125 }
126 
127 int GEMSimpleModel::getSimHitBx(const PSimHit* simhit, CLHEP::HepRandomEngine* engine)
128 {
129  int bx = -999;
130  const LocalPoint simHitPos(simhit->localPosition());
131  const float tof(simhit->timeOfFlight());
132  // random Gaussian time correction due to electronics jitter
133  float randomJitterTime = CLHEP::RandGaussQ::shoot(engine, 0., timeJitter_);
134  const GEMDetId id(simhit->detUnitId());
135  const GEMEtaPartition* roll(geometry_->etaPartition(id));
136  if (!roll)
137  {
138  throw cms::Exception("Geometry")<< "GEMSimpleModel::getSimHitBx() - GEM simhit id does not match any GEM roll id: " << id << "\n";
139  return 999;
140  }
141  if (roll->id().region() == 0)
142  {
143  throw cms::Exception("Geometry") << "GEMSimpleModel::getSimHitBx() - this GEM id is from barrel, which cannot happen: " << roll->id() << "\n";
144  }
145  const double cspeed = 299792458; // signal propagation speed in vacuum in [m/s]
146  const int nstrips = roll->nstrips();
147  float middleStrip = nstrips/2.;
148  LocalPoint middleOfRoll = roll->centreOfStrip(middleStrip);
149  GlobalPoint globMiddleRol = roll->toGlobal(middleOfRoll);
150  double muRadius = sqrt(globMiddleRol.x()*globMiddleRol.x() + globMiddleRol.y()*globMiddleRol.y() +globMiddleRol.z()*globMiddleRol.z());
151  double timeCalibrationOffset_ = (muRadius *1e+9)/(cspeed*1e+2); //[ns]
152 
153  const TrapezoidalStripTopology* top(dynamic_cast<const TrapezoidalStripTopology*> (&(roll->topology())));
154  const float halfStripLength(0.5 * top->stripLength());
155  const float distanceFromEdge(halfStripLength - simHitPos.y());
156 
157  // signal propagation speed in material in [cm/ns]
158  double signalPropagationSpeedTrue = signalPropagationSpeed_ * cspeed * 1e-7; // 1e+2 * 1e-9;
159 
160  // average time for the signal to propagate from the SimHit to the top of a strip
161  const float averagePropagationTime(distanceFromEdge / signalPropagationSpeedTrue);
162  // random Gaussian time correction due to the finite timing resolution of the detector
163  float randomResolutionTime = CLHEP::RandGaussQ::shoot(engine, 0., timeResolution_);
164  const float simhitTime(tof + averageShapingTime_ + randomResolutionTime + averagePropagationTime + randomJitterTime);
165  float referenceTime = 0.;
166  referenceTime = timeCalibrationOffset_ + halfStripLength / signalPropagationSpeedTrue + averageShapingTime_;
167  const float timeDifference(cosmics_ ? (simhitTime - referenceTime) / COSMIC_PAR : simhitTime - referenceTime);
168  // assign the bunch crossing
169  bx = static_cast<int> (std::round((timeDifference) / bxwidth_));
170 
171  // check time
172  const bool debug(false);
173  if (debug)
174  {
175  std::cout << "checktime " << "bx = " << bx << "\tdeltaT = " << timeDifference << "\tsimT = " << simhitTime
176  << "\trefT = " << referenceTime << "\ttof = " << tof << "\tavePropT = " << averagePropagationTime
177  << "\taveRefPropT = " << halfStripLength / signalPropagationSpeedTrue << std::endl;
178  }
179  return bx;
180 }
181 
182 void GEMSimpleModel::simulateNoise(const GEMEtaPartition* roll, CLHEP::HepRandomEngine* engine)
183 //void GEMSimpleModel::simulateNoise(const GEMEtaPartition* roll)
184 {
185  if (!doBkgNoise_)
186  return;
187  const GEMDetId gemId(roll->id());
188  const int nstrips(roll->nstrips());
189  double trArea(0.0);
190  double trStripArea(0.0);
191  if (gemId.region() == 0)
192  {
193  throw cms::Exception("Geometry")
194  << "GEMSynchronizer::simulateNoise() - this GEM id is from barrel, which cannot happen.";
195  }
196  const TrapezoidalStripTopology* top_(dynamic_cast<const TrapezoidalStripTopology*>(&(roll->topology())));
197  const float striplength(top_->stripLength());
198  trStripArea = (roll->pitch()) * striplength;
199  trArea = trStripArea * nstrips;
200  const int nBxing(maxBunch_ - minBunch_ + 1);
201  const float rollRadius(fixedRollRadius_ ? top_->radius() :
202  top_->radius() + CLHEP::RandFlat::shoot(engine, -1.*top_->stripLength()/2., top_->stripLength()/2.));
203 
204 //calculate noise from model
205  double averageNeutralNoiseRatePerRoll = 0.;
206  double averageNoiseElectronRatePerRoll = 0.;
207  double averageNoiseRatePerRoll = 0.;
208  if (gemId.station() == 1)
209  {
210 //simulate neutral background for GE1/1
212  averageNeutralNoiseRatePerRoll = constNeuGE11 * TMath::Exp(slopeNeuGE11 * rollRadius);
213  else
214  averageNeutralNoiseRatePerRoll = constNeuGE11_highRate * TMath::Exp(slopeNeuGE11_highRate * rollRadius);
215 //simulate electron background for GE1/1
217  averageNoiseElectronRatePerRoll = GE11ElecBkgParam0
218  + GE11ElecBkgParam1 * rollRadius
219  + GE11ElecBkgParam2 * rollRadius * rollRadius
220  + GE11ElecBkgParam3 * rollRadius * rollRadius * rollRadius;
221 
222  // Scale up/down for desired instantaneous lumi (reference is 5E34, double from config is in units of 1E34)
223  averageNoiseRatePerRoll = averageNeutralNoiseRatePerRoll + averageNoiseElectronRatePerRoll;
224  averageNoiseRatePerRoll *= instLumi_*rateFact_*1.0/referenceInstLumi;
225  }
226  if (gemId.station() == 2)
227  {
228 //simulate neutral background for GE2/1
230  averageNeutralNoiseRatePerRoll = GE21NeuBkgParam0
231  + GE21NeuBkgParam1 * rollRadius
232  + GE21NeuBkgParam2 * rollRadius * rollRadius
233  + GE21NeuBkgParam3 * rollRadius * rollRadius * rollRadius
234  + GE21NeuBkgParam4 * rollRadius * rollRadius * rollRadius * rollRadius
235  + GE21NeuBkgParam5 * rollRadius * rollRadius * rollRadius * rollRadius * rollRadius;
236  else
237  averageNeutralNoiseRatePerRoll = GE21ModNeuBkgParam0
238  + GE21ModNeuBkgParam1 * rollRadius
239  + GE21ModNeuBkgParam2 * rollRadius * rollRadius
240  + GE21ModNeuBkgParam3 * rollRadius * rollRadius * rollRadius
241  + GE21ModNeuBkgParam4 * rollRadius * rollRadius * rollRadius * rollRadius
242  + GE21ModNeuBkgParam5 * rollRadius * rollRadius * rollRadius * rollRadius * rollRadius;
243 //simulate electron background for GE2/1
245  averageNoiseElectronRatePerRoll = constElecGE21 * TMath::Exp(slopeElecGE21 * rollRadius);
246  // Scale up/down for desired instantaneous lumi (reference is 5E34, double from config is in units of 1E34)
247  averageNoiseRatePerRoll = averageNeutralNoiseRatePerRoll + averageNoiseElectronRatePerRoll;
248  averageNoiseRatePerRoll *= instLumi_*rateFact_*1.0/referenceInstLumi;
249  }
250 //simulate intrinsic noise
252  {
253  const double aveIntrinsicNoisePerStrip(averageNoiseRate_ * nBxing * bxwidth_ * trStripArea * 1.0e-9);
254  for(int j = 0; j < nstrips; ++j)
255  {
256  CLHEP::RandPoissonQ randPoissonQ(*engine, aveIntrinsicNoisePerStrip);
257  const int n_intrHits(randPoissonQ.fire());
258 
259  for (int k = 0; k < n_intrHits; k++ )
260  {
261  const int time_hit(static_cast<int>(CLHEP::RandFlat::shoot(engine, nBxing)) + minBunch_);
262  std::pair<int, int> digi(k+1,time_hit);
263  strips_.insert(digi);
264  }
265  }
266  }//end simulate intrinsic noise
267 //simulate bkg contribution
268  const double averageNoise(averageNoiseRatePerRoll * nBxing * bxwidth_ * trArea * 1.0e-9);
269  CLHEP::RandPoissonQ randPoissonQ(*engine, averageNoise);
270  const int n_hits(randPoissonQ.fire());
271  for (int i = 0; i < n_hits; ++i)
272  {
273  const int centralStrip(static_cast<int> (CLHEP::RandFlat::shoot(engine, 1, nstrips)));
274  const int time_hit(static_cast<int>(CLHEP::RandFlat::shoot(engine, nBxing)) + minBunch_);
275  if (doNoiseCLS_)
276  {
277  std::vector < std::pair<int, int> > cluster_;
278  cluster_.clear();
279  cluster_.push_back(std::pair<int, int>(centralStrip, time_hit));
280  int clusterSize((CLHEP::RandFlat::shoot(engine)) <= 0.53 ? 1 : 2);
281  if (clusterSize == 2)
282  {
283  if(CLHEP::RandFlat::shoot(engine) < 0.5)
284  {
285  if (CLHEP::RandFlat::shoot(engine) < averageEfficiency_ && (centralStrip - 1 > 0))
286  cluster_.push_back(std::pair<int, int>(centralStrip - 1, time_hit));
287  }
288  else
289  {
290  if (CLHEP::RandFlat::shoot(engine) < averageEfficiency_ && (centralStrip + 1 <= nstrips))
291  cluster_.push_back(std::pair<int, int>(centralStrip + 1, time_hit));
292  }
293  }
294  for (auto & digi : cluster_)
295  {
296  strips_.insert(digi);
297  }
298  } //end doNoiseCLS_
299  else
300  {
301  std::pair<int, int> digi(centralStrip, time_hit);
302  strips_.insert(digi);
303  }
304  }
305  return;
306 }
307 
308 std::vector<std::pair<int, int> > GEMSimpleModel::simulateClustering(const GEMEtaPartition* roll,
309  const PSimHit* simHit, const int bx, CLHEP::HepRandomEngine* engine)
310 {
311  const StripTopology& topology = roll->specificTopology(); // const LocalPoint& entry(simHit->entryPoint());
312  const LocalPoint& hit_position(simHit->localPosition());
313  const int nstrips(roll->nstrips());
314  int centralStrip = 0;
315  if (!(topology.channel(hit_position) + 1 > nstrips))
316  centralStrip = topology.channel(hit_position) + 1;
317  else
318  centralStrip = topology.channel(hit_position);
319  GlobalPoint pointSimHit = roll->toGlobal(hit_position);
320  GlobalPoint pointDigiHit = roll->toGlobal(roll->centreOfStrip(centralStrip));
321  double deltaX = pointSimHit.x() - pointDigiHit.x();
322 // Add central digi to cluster vector
323  std::vector < std::pair<int, int> > cluster_;
324  cluster_.clear();
325  cluster_.push_back(std::pair<int, int>(centralStrip, bx));
326 //simulate cross talk
327  int clusterSize((CLHEP::RandFlat::shoot(engine)) <= 0.53 ? 1 : 2);
328  if (clusterSize == 2)
329  {
330  if (deltaX <= 0)
331  {
332  if (CLHEP::RandFlat::shoot(engine) < averageEfficiency_ && (centralStrip - 1 > 0))
333  cluster_.push_back(std::pair<int, int>(centralStrip - 1, bx));
334  }
335  else
336  {
337  if (CLHEP::RandFlat::shoot(engine) < averageEfficiency_ && (centralStrip + 1 <= nstrips))
338  cluster_.push_back(std::pair<int, int>(centralStrip + 1, bx));
339  }
340  }
341  return cluster_;
342 }
double GE21ModNeuBkgParam1
double signalPropagationSpeed_
double GE21ModNeuBkgParam4
edm::DetSet< GEMDigiSimLink > GEMDigiSimLinks
Definition: GEMDigiModel.h:37
double slopeNeuGE11_highRate
CaloTopology const * topology(0)
double constNeuGE11_highRate
GlobalPoint toGlobal(const Local2DPoint &lp) const
Conversion to the global R.F. from the R.F. of the GeomDet.
Definition: GeomDet.h:54
double averageNoiseRate_
T y() const
Definition: PV3DBase.h:63
int getSimHitBx(const PSimHit *, CLHEP::HepRandomEngine *)
void setup() override
Definition: config.py:1
GEMDigiSimLinks theGemDigiSimLinks_
Definition: GEMDigiModel.h:80
double slopeElecGE21
const Topology & topology() const
const GEMEtaPartition * etaPartition(GEMDetId id) const
Return a GEMEtaPartition given its id.
Definition: GEMGeometry.cc:99
double GE21ModNeuBkgParam5
GEMDetId id() const
LocalPoint centreOfStrip(int strip) const
uint32_t rawId() const
get the raw id
Definition: DetId.h:43
int nstrips() const
number of readout strips in partition
double GE11ElecBkgParam2
float timeOfFlight() const
Definition: PSimHit.h:69
double GE11ElecBkgParam0
bool simulateIntrinsicNoise_
double GE11ElecBkgParam3
Local3DPoint localPosition() const
Definition: PSimHit.h:44
T sqrt(T t)
Definition: SSEVec.h:18
double averageEfficiency_
T z() const
Definition: PV3DBase.h:64
double GE11ElecBkgParam1
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::vector< std::pair< int, int > > simulateClustering(const GEMEtaPartition *, const PSimHit *, const int, CLHEP::HepRandomEngine *) override
const StripTopology & specificTopology() const
bool simulateLowNeutralRate_
GEMSimpleModel(const edm::ParameterSet &)
virtual int channel(const LocalPoint &p) const =0
float pitch() const
double GE21NeuBkgParam2
int k[5][pyjets_maxn]
bool simulateElectronBkg_
double GE21ModNeuBkgParam2
#define debug
Definition: HDRShower.cc:19
double GE21ModNeuBkgParam0
double constElecGE21
double GE21NeuBkgParam4
double GE21ModNeuBkgParam3
double GE21NeuBkgParam3
double GE21NeuBkgParam0
void simulateNoise(const GEMEtaPartition *, CLHEP::HepRandomEngine *) override
const GEMGeometry * geometry_
Definition: GEMDigiModel.h:63
double GE21NeuBkgParam5
double averageShapingTime_
std::set< std::pair< int, int > > strips_
Definition: GEMDigiModel.h:65
const double referenceInstLumi
void clear()
Definition: DetSet.h:69
DetectorHitMap detectorHitMap_
Definition: GEMDigiModel.h:78
double timeResolution_
std::vector< PSimHit > PSimHitContainer
StripDigiSimLinks stripDigiSimLinks_
Definition: GEMDigiModel.h:79
double GE21NeuBkgParam1
edm::DetSet< StripDigiSimLink > StripDigiSimLinks
Definition: GEMDigiModel.h:36
T x() const
Definition: PV3DBase.h:62
void simulateSignal(const GEMEtaPartition *, const edm::PSimHitContainer &, CLHEP::HepRandomEngine *) override
unsigned int detUnitId() const
Definition: PSimHit.h:93