File indexing completed on 2023-03-17 11:25:24
0001 #include "SimMuon/GEMDigitizer/interface/ME0PreRecoGaussianModel.h"
0002 #include "Geometry/GEMGeometry/interface/ME0EtaPartitionSpecs.h"
0003 #include "Geometry/CommonTopologies/interface/TrapezoidalStripTopology.h"
0004 #include "Geometry/GEMGeometry/interface/ME0Geometry.h"
0005
0006 #include "FWCore/ServiceRegistry/interface/Service.h"
0007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0008
0009 #include "CLHEP/Random/RandFlat.h"
0010 #include "CLHEP/Random/RandGaussQ.h"
0011 #include "CLHEP/Random/RandPoissonQ.h"
0012
0013 #include <cmath>
0014 #include <utility>
0015 #include <map>
0016
0017 const int bxwidth = 25;
0018
0019 ME0PreRecoGaussianModel::ME0PreRecoGaussianModel(const edm::ParameterSet& config)
0020 : ME0DigiPreRecoModel(config),
0021 sigma_t(config.getParameter<double>("timeResolution")),
0022 sigma_u(config.getParameter<double>("phiResolution")),
0023 sigma_v(config.getParameter<double>("etaResolution")),
0024 error_u(config.getParameter<double>("phiError")),
0025 error_v(config.getParameter<double>("etaError")),
0026 gaussianSmearing_(config.getParameter<bool>("gaussianSmearing")),
0027 constPhiSmearing_(config.getParameter<bool>("constantPhiSpatialResolution")),
0028 corr(config.getParameter<bool>("useCorrelation")),
0029 etaproj(config.getParameter<bool>("useEtaProjectiveGEO")),
0030 digitizeOnlyMuons_(config.getParameter<bool>("digitizeOnlyMuons")),
0031 averageEfficiency_(config.getParameter<double>("averageEfficiency")),
0032
0033
0034 simulateElectronBkg_(config.getParameter<bool>("simulateElectronBkg")),
0035 simulateNeutralBkg_(config.getParameter<bool>("simulateNeutralBkg")),
0036 minBunch_(config.getParameter<int>("minBunch")),
0037 maxBunch_(config.getParameter<int>("maxBunch")),
0038 instLumi_(config.getParameter<double>("instLumi")),
0039 rateFact_(config.getParameter<double>("rateFact")),
0040 referenceInstLumi_(config.getParameter<double>("referenceInstLumi")) {
0041
0042
0043 neuBkg.push_back(0.00386257);
0044 neuBkg.push_back(6344.65);
0045 neuBkg.push_back(16627700);
0046 neuBkg.push_back(-102098);
0047
0048 eleBkg.push_back(0.00171409);
0049 eleBkg.push_back(4900.56);
0050 eleBkg.push_back(710909);
0051 eleBkg.push_back(-4327.25);
0052 }
0053
0054 ME0PreRecoGaussianModel::~ME0PreRecoGaussianModel() {}
0055
0056 void ME0PreRecoGaussianModel::simulateSignal(const ME0EtaPartition* roll,
0057 const edm::PSimHitContainer& simHits,
0058 CLHEP::HepRandomEngine* engine) {
0059 for (const auto& hit : simHits) {
0060
0061 if (std::abs(hit.particleType()) != 13 && digitizeOnlyMuons_)
0062 continue;
0063
0064
0065 if (hit.timeOfFlight() < (2 * minBunch_ + 1) * bxwidth * 1.0 / 2 ||
0066 hit.timeOfFlight() > (2 * maxBunch_ + 3) * bxwidth * 1.0 / 2)
0067 continue;
0068
0069 if (CLHEP::RandFlat::shoot(engine) > averageEfficiency_)
0070 continue;
0071
0072 auto entry = hit.entryPoint();
0073 double x = 0.0, y = 0.0;
0074
0075 double sigma_u_new = sigma_u;
0076 if (constPhiSmearing_)
0077 sigma_u_new = correctSigmaU(roll, entry.y());
0078
0079 if (gaussianSmearing_) {
0080 x = CLHEP::RandGaussQ::shoot(engine, entry.x(), sigma_u_new);
0081 y = CLHEP::RandGaussQ::shoot(engine, entry.y(), sigma_v);
0082 } else {
0083 x = entry.x() + (CLHEP::RandFlat::shoot(engine) - 0.5) * sigma_u_new;
0084 y = entry.y() + (CLHEP::RandFlat::shoot(engine) - 0.5) * sigma_v;
0085 }
0086 double ex = sigma_u_new;
0087 double ey = sigma_v;
0088 double corr = 0.;
0089 double tof = CLHEP::RandGaussQ::shoot(engine, hit.timeOfFlight(), sigma_t);
0090 int pdgid = hit.particleType();
0091 if (ex == 0)
0092 ex = error_u;
0093 if (ey == 0)
0094 ey = error_v;
0095
0096 int evtId = hit.eventId().event();
0097 int bx = hit.eventId().bunchCrossing();
0098 int procType = hit.processType();
0099 int res = 1;
0100 if (!(evtId == 0 && bx == 0 && procType == 0))
0101 res = 2;
0102
0103 digi_.emplace(x, y, ex, ey, corr, tof, pdgid, res);
0104
0105 edm::LogVerbatim("ME0PreRecoGaussianModel")
0106 << "[ME0PreRecoDigi :: simulateSignal] :: simhit in " << roll->id() << " at loc x = " << std::setw(8)
0107 << entry.x() << " [cm]"
0108 << " loc y = " << std::setw(8) << entry.y() << " [cm] time = " << std::setw(8) << hit.timeOfFlight()
0109 << " [ns] pdgid = " << std::showpos << std::setw(4) << pdgid;
0110 edm::LogVerbatim("ME0PreRecoGaussianModel")
0111 << "[ME0PreRecoDigi :: simulateSignal] :: digi in " << roll->id() << " at loc x = " << std::setw(8) << x
0112 << " [cm] loc y = " << std::setw(8) << y << " [cm]"
0113 << " time = " << std::setw(8) << tof << " [ns]";
0114 edm::LogVerbatim("ME0PreRecoGaussianModel")
0115 << "[ME0PreRecoDigi :: simulateSignal] :: digi in " << roll->id() << " with DX = " << std::setw(8)
0116 << (entry.x() - x) << " [cm]"
0117 << " DY = " << std::setw(8) << (entry.y() - y) << " [cm] DT = " << std::setw(8) << (hit.timeOfFlight() - tof)
0118 << " [ns]";
0119 }
0120 }
0121
0122 void ME0PreRecoGaussianModel::simulateNoise(const ME0EtaPartition* roll, CLHEP::HepRandomEngine* engine) {
0123 double trArea(0.0);
0124 const ME0DetId me0Id(roll->id());
0125
0126
0127
0128
0129 if (me0Id.region() == 0) {
0130 throw cms::Exception("Geometry") << "Asking TrapezoidalStripTopology from a ME0 will fail";
0131 }
0132 const TrapezoidalStripTopology* top_(dynamic_cast<const TrapezoidalStripTopology*>(&(roll->topology())));
0133
0134 auto& parameters(roll->specs()->parameters());
0135 double bottomLength(parameters[0]);
0136 bottomLength = 2 * bottomLength;
0137 double topLength(parameters[1]);
0138 topLength = 2 * topLength;
0139 double height(parameters[2]);
0140 height = 2 * height;
0141 double myTanPhi = (topLength - bottomLength) / (height * 2);
0142 double rollRadius = top_->radius();
0143 trArea = height * (topLength + bottomLength) / 2.0;
0144
0145
0146
0147 double initialHeight = sigma_v;
0148 if (sigma_v < 1.0)
0149 initialHeight = 1.0;
0150 double heightIt = initialHeight;
0151 int heightbins = height / heightIt;
0152
0153 edm::LogVerbatim("ME0PreRecoGaussianModelNoise")
0154 << "[ME0PreRecoDigi :: sNoise][" << roll->id().rawId() << "] :: roll with id = " << roll->id();
0155 edm::LogVerbatim("ME0PreRecoGaussianModelNoise") << "[ME0PreRecoDigi :: sNoise][" << roll->id().rawId()
0156 << "] :: extracting parameters from the TrapezoidalStripTopology";
0157 edm::LogVerbatim("ME0PreRecoGaussianModelNoise")
0158 << "[ME0PreRecoDigi :: sNoise][" << roll->id().rawId() << "] :: bottom = " << bottomLength
0159 << " [cm] top = " << topLength << " [cm] height = " << height << " [cm]"
0160 << " area = " << trArea << " [cm^2] Rmid = " << rollRadius
0161 << " [cm] => Rmin = " << rollRadius - height * 1.0 / 2.0 << " [cm] Rmax = " << rollRadius + height * 1.0 / 2.0
0162 << " [cm]";
0163 edm::LogVerbatim("ME0PreRecoGaussianModelNoise")
0164 << "[ME0PreRecoDigi :: sNoise][" << roll->id().rawId() << "] :: heightbins = " << heightbins;
0165
0166 for (int hx = 0; hx < heightbins; ++hx) {
0167 double bottomIt = bottomLength + hx * 2 * tan(10. / 180 * 3.14) * heightIt;
0168 double topIt = bottomLength + (hx + 1) * 2 * tan(10. / 180 * 3.14) * heightIt;
0169 if (hx == heightbins - 1) {
0170 topIt = topLength;
0171 heightIt = height - hx * heightIt;
0172 }
0173 double areaIt = heightIt * (bottomIt + topIt) * 1.0 / 2;
0174
0175 edm::LogVerbatim("ME0PreRecoGaussianModelNoise")
0176 << "[ME0PreRecoDigi :: sNoise][" << roll->id().rawId() << "] :: height = " << std::setw(12) << heightIt
0177 << " [cm] bottom = " << std::setw(12) << bottomIt << " [cm]"
0178 << " top = " << std::setw(12) << topIt << " [cm] area = " << std::setw(12) << areaIt
0179 << " [cm^2] || sin(10) = " << sin(10. / 180 * 3.14);
0180
0181 double myRandY = CLHEP::RandFlat::shoot(engine);
0182 double y0_rand = (hx + myRandY) * heightIt;
0183 if (hx == heightbins - 1)
0184 y0_rand = hx * initialHeight + myRandY * heightIt;
0185 double yy_rand =
0186 (y0_rand -
0187 height * 1.0 / 2);
0188 double yy_glob = rollRadius + yy_rand;
0189
0190 const float rSqrtR = yy_glob * sqrt(yy_glob);
0191 double xMax = topLength / 2.0 - (height / 2.0 - yy_rand) * myTanPhi;
0192
0193 double sigma_u_new = sigma_u;
0194 if (constPhiSmearing_)
0195 sigma_u_new = correctSigmaU(roll, yy_rand);
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 if (simulateElectronBkg_) {
0209
0210
0211 double averageElectronRatePerRoll =
0212 eleBkg[0] * rSqrtR * std::exp(eleBkg[1] / rSqrtR) + eleBkg[2] / rSqrtR + eleBkg[3] / (sqrt(yy_glob));
0213
0214 averageElectronRatePerRoll *= instLumi_ * rateFact_ * 1.0 / referenceInstLumi_;
0215
0216
0217 const double averageElecRate(averageElectronRatePerRoll * (maxBunch_ - minBunch_ + 1) * (bxwidth * 1.0e-9) *
0218 areaIt);
0219
0220 edm::LogVerbatim("ME0PreRecoGaussianModelNoise")
0221 << "[ME0PreRecoDigi :: elebkg][" << roll->id().rawId() << "]"
0222 << " evaluation of Background Hit Rate at this coord :: " << std::setw(12) << averageElectronRatePerRoll
0223 << " [Hz/cm^2]"
0224 << " x 9 x 25*10^-9 [s] x Area (of strip = " << std::setw(12) << areaIt << " [cm^2]) ==> " << std::setw(12)
0225 << averageElecRate << " [hits]";
0226
0227 bool ele_eff = (CLHEP::RandFlat::shoot(engine) < averageElecRate) ? true : false;
0228
0229 edm::LogVerbatim("ME0PreRecoGaussianModelNoise")
0230 << "[ME0PreRecoDigi :: elebkg][" << roll->id().rawId() << "] :: myRandY = " << std::setw(12) << myRandY
0231 << " => local y = " << std::setw(12) << yy_rand << " [cm]"
0232 << " => global y (global R) = " << std::setw(12) << yy_glob << " [cm] || Probability = " << std::setw(12)
0233 << averageElecRate << " => efficient? " << ele_eff << std::endl;
0234
0235 if (ele_eff) {
0236
0237 double myRandX = CLHEP::RandFlat::shoot(engine);
0238 double xx_rand = 2 * xMax * (myRandX - 0.5);
0239 double ex = sigma_u_new;
0240 double ey = sigma_v;
0241 double corr = 0.;
0242
0243 double myrandBX = CLHEP::RandFlat::shoot(engine);
0244 int bx = int((maxBunch_ - minBunch_ + 1) * myrandBX) + minBunch_;
0245
0246 double myrandT = CLHEP::RandFlat::shoot(engine);
0247 double minBXtime = (bx - 0.5) * bxwidth;
0248 double time = myrandT * bxwidth + minBXtime;
0249 double myrandP = CLHEP::RandFlat::shoot(engine);
0250 int pdgid = 0;
0251 if (myrandP <= 0.5)
0252 pdgid = -11;
0253 else
0254 pdgid = 11;
0255 if (ex == 0)
0256 ex = error_u;
0257 if (ey == 0)
0258 ey = error_v;
0259
0260 digi_.emplace(xx_rand, yy_rand, ex, ey, corr, time, pdgid, 0);
0261
0262 edm::LogVerbatim("ME0PreRecoGaussianModelNoise")
0263 << "[ME0PreRecoDigi :: elebkg][" << roll->id().rawId() << "] =====> electron hit in " << roll->id()
0264 << " pdgid = " << pdgid << " bx = " << bx << " ==> digitized"
0265 << " at loc x = " << xx_rand << " loc y = " << yy_rand << " time = " << time << " [ns]";
0266 }
0267 }
0268
0269
0270
0271 if (simulateNeutralBkg_) {
0272
0273
0274 double averageNeutralRatePerRoll =
0275 neuBkg[0] * yy_glob * std::exp(neuBkg[1] / rSqrtR) + neuBkg[2] / rSqrtR + neuBkg[3] / (sqrt(yy_glob));
0276
0277 averageNeutralRatePerRoll *= instLumi_ * rateFact_ * 1.0 / referenceInstLumi_;
0278
0279
0280 const double averageNeutrRate(averageNeutralRatePerRoll * (maxBunch_ - minBunch_ + 1) * (bxwidth * 1.0e-9) *
0281 areaIt);
0282
0283 edm::LogVerbatim("ME0PreRecoGaussianModelNoise")
0284 << "[ME0PreRecoDigi :: neubkg][" << roll->id().rawId() << "]"
0285 << " evaluation of Background Hit Rate at this coord :: " << std::setw(12) << averageNeutralRatePerRoll
0286 << " [Hz/cm^2]"
0287 << " x 9 x 25*10^-9 [s] x Area (of strip = " << std::setw(12) << areaIt << " [cm^2]) ==> " << std::setw(12)
0288 << averageNeutrRate << " [hits]";
0289
0290 bool neu_eff = (CLHEP::RandFlat::shoot(engine) < averageNeutrRate) ? true : false;
0291
0292 edm::LogVerbatim("ME0PreRecoGaussianModelNoise")
0293 << "[ME0PreRecoDigi :: neubkg][" << roll->id().rawId() << "] :: myRandY = " << std::setw(12) << myRandY
0294 << " => local y = " << std::setw(12) << yy_rand << " [cm]"
0295 << " => global y (global R) = " << std::setw(12) << yy_glob << " [cm] || Probability = " << std::setw(12)
0296 << averageNeutrRate << " => efficient? " << neu_eff << std::endl;
0297
0298 if (neu_eff) {
0299
0300 double myRandX = CLHEP::RandFlat::shoot(engine);
0301 double xx_rand = 2 * xMax * (myRandX - 0.5);
0302 double ex = sigma_u_new;
0303 double ey = sigma_v;
0304 double corr = 0.;
0305
0306 double myrandBX = CLHEP::RandFlat::shoot(engine);
0307 int bx = int((maxBunch_ - minBunch_ + 1) * myrandBX) + minBunch_;
0308
0309 double myrandT = CLHEP::RandFlat::shoot(engine);
0310 double minBXtime = (bx - 0.5) * bxwidth;
0311 double time = myrandT * bxwidth + minBXtime;
0312 int pdgid = 0;
0313 double myrandP = CLHEP::RandFlat::shoot(engine);
0314 if (myrandP <= 0.08)
0315 pdgid = 2112;
0316 else
0317 pdgid =
0318 22;
0319 if (ex == 0)
0320 ex = error_u;
0321 if (ey == 0)
0322 ey = error_v;
0323
0324 digi_.emplace(xx_rand, yy_rand, ex, ey, corr, time, pdgid, 0);
0325
0326 edm::LogVerbatim("ME0PreRecoGaussianModelNoise")
0327 << "[ME0PreRecoDigi :: neubkg][" << roll->id().rawId() << "] ======> neutral hit in " << roll->id()
0328 << " pdgid = " << pdgid << " bx = " << bx << " ==> digitized"
0329 << " at loc x = " << xx_rand << " loc y = " << yy_rand << " time = " << time << " [ns]";
0330 }
0331
0332 }
0333 }
0334 }
0335
0336 double ME0PreRecoGaussianModel::correctSigmaU(const ME0EtaPartition* roll, double y) {
0337 const TrapezoidalStripTopology* top_(dynamic_cast<const TrapezoidalStripTopology*>(&(roll->topology())));
0338 auto& parameters(roll->specs()->parameters());
0339 double height(parameters[2]);
0340 double rollRadius = top_->radius();
0341 double Rmax = rollRadius + height;
0342 double Rx = rollRadius + y;
0343 double sigma_u_new = Rx / Rmax * sigma_u;
0344 return sigma_u_new;
0345 }