File indexing completed on 2024-04-06 12:29:32
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "SimCalorimetry/HcalSimAlgos/interface/HPDIonFeedbackSim.h"
0012 #include "SimCalorimetry/HcalSimAlgos/interface/HcalShapes.h"
0013 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVShape.h"
0014 #include "CondFormats/HcalObjects/interface/HcalGain.h"
0015 #include "CondFormats/HcalObjects/interface/HcalGainWidth.h"
0016 #include "DataFormats/HcalDetId/interface/HcalGenericDetId.h"
0017 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0018 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0019 #include "FWCore/PluginManager/interface/PluginManager.h"
0020 #include "FWCore/PluginManager/interface/standard.h"
0021
0022 #include "CLHEP/Random/RandBinomial.h"
0023 #include "CLHEP/Random/RandGaussQ.h"
0024 #include "CLHEP/Random/RandPoissonQ.h"
0025
0026 using namespace edm;
0027 using namespace std;
0028
0029
0030 static const double pe2Charge = 0.333333;
0031
0032 HPDIonFeedbackSim::HPDIonFeedbackSim(const edm::ParameterSet& iConfig, const CaloShapes* shapes)
0033 : theDbService(nullptr), theShapes(shapes) {}
0034
0035 HPDIonFeedbackSim::~HPDIonFeedbackSim() {}
0036
0037 double HPDIonFeedbackSim::getIonFeedback(
0038 DetId detId, double signal, double pedWidth, bool doThermal, bool isInGeV, CLHEP::HepRandomEngine* engine) {
0039
0040
0041 double GeVperfC = 1.;
0042 if (isInGeV)
0043 GeVperfC = 1. / fCtoGeV(detId);
0044
0045 double charge = signal / GeVperfC;
0046
0047 double noise = 0.;
0048 if (charge > 3. * pedWidth) {
0049 int npe = int(charge / pe2Charge);
0050 if (doThermal) {
0051 double electronEmission = 0.08;
0052 CLHEP::RandPoissonQ theRandPoissonQ(*engine, electronEmission);
0053 npe += theRandPoissonQ.fire();
0054 }
0055
0056 noise = correctPE(detId, npe, engine) - npe;
0057 }
0058 return (noise * GeVperfC);
0059 }
0060
0061 double HPDIonFeedbackSim::correctPE(const DetId& detId, double npe, CLHEP::HepRandomEngine* engine) const {
0062 double rateInTail = 0.000211988;
0063 double rateInSecondTail = 4.61579e-06;
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 double p4 = 2.06117e+01;
0075 double p5 = 1.09239e+01;
0076
0077
0078
0079 double p7 = 5.45548e+01;
0080 double p8 = 1.59696e+01;
0081
0082 double noise = 0.;
0083 int nFirst = (int)(CLHEP::RandBinomial::shoot(engine, npe, rateInTail));
0084 int nSecond = (int)(CLHEP::RandBinomial::shoot(engine, npe, rateInSecondTail));
0085
0086 for (int j = 0; j < nFirst; ++j) {
0087 noise += CLHEP::RandGaussQ::shoot(engine, p4, p5);
0088 }
0089 for (int j = 0; j < nSecond; ++j) {
0090 noise += CLHEP::RandGaussQ::shoot(engine, p7, p8);
0091 }
0092
0093 return npe + std::max(noise / pe2Charge, 0.);
0094 }
0095
0096 void HPDIonFeedbackSim::addThermalNoise(CaloSamples& samples, CLHEP::HepRandomEngine* engine) {
0097
0098
0099 double meanPE = 0.02;
0100 DetId detId(samples.id());
0101 int nSamples = samples.size();
0102 const CaloVShape* shape = theShapes->shape(detId);
0103 for (int i = 0; i < nSamples; ++i) {
0104 CLHEP::RandPoissonQ theRandPoissonQ(*engine, meanPE);
0105 double npe = theRandPoissonQ.fire();
0106
0107 if (npe > 0.) {
0108
0109 npe = correctPE(detId, npe, engine);
0110 for (int j = i; j < nSamples; ++j) {
0111 double timeFromPE = (j - i) * 25.;
0112 samples[j] += (*shape)(timeFromPE)*npe;
0113 }
0114 }
0115 }
0116 }
0117
0118 double HPDIonFeedbackSim::fCtoGeV(const DetId& detId) const {
0119 assert(theDbService != nullptr);
0120 HcalGenericDetId hcalGenDetId(detId);
0121 const HcalGain* gains = theDbService->getGain(hcalGenDetId);
0122 const HcalGainWidth* gwidths = theDbService->getGainWidth(hcalGenDetId);
0123 double result = 0.0;
0124 if (!gains || !gwidths) {
0125 edm::LogError("HcalAmplifier") << "Could not fetch HCAL conditions for channel " << hcalGenDetId;
0126 } else {
0127
0128 result = gains->getValue(0);
0129 }
0130 return result;
0131 }