10 #include "CLHEP/Random/RandGaussQ.h"
41 constexpr
double m_pion = 139.571;
42 constexpr
double m_kaon = 493.677;
43 constexpr
double m_electron = 0.511;
44 constexpr
double m_muon = 105.658;
45 constexpr
double m_proton = 938.272;
51 makeDigiSimLinks_(conf_common.getUntrackedParameter<
bool>(
"makeDigiSimLinks",
true)),
52 use_ineff_from_db_(conf_specific.getParameter<
bool>(
"Inefficiency_DB")),
53 use_module_killing_(conf_specific.getParameter<
bool>(
"KillModules")),
54 use_deadmodule_DB_(conf_specific.getParameter<
bool>(
"DeadModules_DB")),
56 use_LorentzAngle_DB_(conf_specific.getParameter<
bool>(
"LorentzAngle_DB")),
59 deadModules_(use_deadmodule_DB_ ?
Parameters() : conf_specific.getParameter<
Parameters>(
"DeadModules")),
63 GeVperElectron_(3.61E-09),
64 alpha2Order_(conf_specific.getParameter<
bool>(
"Alpha2Order")),
65 addXtalk_(conf_specific.getParameter<
bool>(
"AddXTalk")),
67 interstripCoupling_(conf_specific.getParameter<double>(
"InterstripCoupling")),
69 Sigma0_(conf_specific.getParameter<double>(
"SigmaZero")),
70 SigmaCoeff_(conf_specific.getParameter<double>(
"SigmaCoeff")),
76 clusterWidth_(conf_specific.getParameter<double>(
"ClusterWidth")),
82 thePhase2ReadoutMode_(conf_specific.getParameter<
int>(
"Phase2ReadoutMode")),
89 theElectronPerADC_(conf_specific.getParameter<double>(
"ElectronPerAdc")),
92 theAdcFullScale_(conf_specific.getParameter<
int>(
"AdcFullScale")),
96 theNoiseInElectrons_(conf_specific.getParameter<double>(
"NoiseInElectrons")),
99 theReadoutNoise_(conf_specific.getParameter<double>(
"ReadoutNoiseInElec")),
104 theThresholdInE_Endcap_(conf_specific.getParameter<double>(
"ThresholdInElectrons_Endcap")),
105 theThresholdInE_Barrel_(conf_specific.getParameter<double>(
"ThresholdInElectrons_Barrel")),
108 theThresholdSmearing_Endcap_(conf_specific.getParameter<double>(
"ThresholdSmearing_Endcap")),
109 theThresholdSmearing_Barrel_(conf_specific.getParameter<double>(
"ThresholdSmearing_Barrel")),
112 theHIPThresholdInE_Endcap_(conf_specific.getParameter<double>(
"HIPThresholdInElectrons_Endcap")),
113 theHIPThresholdInE_Barrel_(conf_specific.getParameter<double>(
"HIPThresholdInElectrons_Barrel")),
116 theTofLowerCut_(conf_specific.getParameter<double>(
"TofLowerCut")),
117 theTofUpperCut_(conf_specific.getParameter<double>(
"TofUpperCut")),
120 tanLorentzAnglePerTesla_Endcap_(
121 use_LorentzAngle_DB_ ? 0.0 : conf_specific.getParameter<double>(
"TanLorentzAnglePerTesla_Endcap")),
122 tanLorentzAnglePerTesla_Barrel_(
123 use_LorentzAngle_DB_ ? 0.0 : conf_specific.getParameter<double>(
"TanLorentzAnglePerTesla_Barrel")),
126 addNoise_(conf_specific.getParameter<
bool>(
"AddNoise")),
129 addNoisyPixels_(conf_specific.getParameter<
bool>(
"AddNoisyPixels")),
132 fluctuateCharge_(conf_specific.getUntrackedParameter<
bool>(
"FluctuateCharge",
true)),
135 addPixelInefficiency_(conf_specific.getParameter<
bool>(
"AddInefficiency")),
138 addThresholdSmearing_(conf_specific.getParameter<
bool>(
"AddThresholdSmearing")),
141 pseudoRadDamage_(conf_specific.exists(
"PseudoRadDamage") ? conf_specific.getParameter<double>(
"PseudoRadDamage")
143 pseudoRadDamageRadius_(conf_specific.exists(
"PseudoRadDamageRadius")
144 ? conf_specific.getParameter<double>(
"PseudoRadDamageRadius")
150 tMax_(conf_common.getParameter<double>(
"DeltaProductionCut")),
152 badPixels_(conf_specific.getParameter<
Parameters>(
"CellsToKill")),
156 theSiPixelGainCalibrationService_(
158 subdetEfficiencies_(conf_specific) {
159 LogDebug(
"Phase2TrackerDigitizerAlgorithm")
160 <<
"Phase2TrackerDigitizerAlgorithm constructed\n"
161 <<
"Configuration parameters:\n"
162 <<
"Threshold/Gain = "
165 <<
" ADC Scale (in bits) " <<
theAdcFullScale_ <<
" The delta cut-off is set to " <<
tMax_ <<
" pix-inefficiency "
170 LogDebug(
"Phase2TrackerDigitizerAlgorithm") <<
"Phase2TrackerDigitizerAlgorithm deleted";
184 const PSimHit&
hit, std::vector<DigitizerUtility::EnergyDepositUnit>& ionization_points)
const {
186 constexpr
float SegmentLength = 0.0010;
191 float length = direction.
mag();
193 int NumberOfSegments = static_cast<int>(length / SegmentLength);
194 if (NumberOfSegments < 1)
195 NumberOfSegments = 1;
196 LogDebug(
"Phase2TrackerDigitizerAlgorithm")
197 <<
"enter primary_ionzation " << NumberOfSegments <<
" shift = " <<
hit.exitPoint().
x() -
hit.entryPoint().
x()
198 <<
" " <<
hit.exitPoint().
y() -
hit.entryPoint().
y() <<
" " <<
hit.exitPoint().
z() -
hit.entryPoint().
z() <<
" "
199 <<
hit.particleType() <<
" " <<
hit.pabs();
201 std::vector<float> elossVector;
202 elossVector.reserve(NumberOfSegments);
207 ionization_points.reserve(NumberOfSegments);
210 for (
size_t i = 0;
i < elossVector.size(); ++
i) {
217 ionization_points.push_back(edu);
218 LogDebug(
"Phase2TrackerDigitizerAlgorithm")
219 <<
i <<
" " << edu.
x() <<
" " << edu.
y() <<
" " << edu.
z() <<
" " << edu.
energy();
229 float particleMomentum,
233 std::vector<float>& elossVector)
const {
239 double particleMass = ::m_pion;
243 particleMass = ::m_electron;
245 particleMass = ::m_muon;
247 particleMass = ::m_kaon;
248 else if (pid == 2212)
249 particleMass = ::m_proton;
252 float segmentLength = length / NumberOfSegs;
256 double segmentEloss = (1000. * eloss) / NumberOfSegs;
257 for (
int i = 0;
i < NumberOfSegs; ++
i) {
263 double deltaCutoff =
tMax_;
264 float de =
fluctuate_->SampleFluctuations(particleMomentum * 1000.,
271 elossVector.push_back(de);
276 float ratio = eloss / sum;
282 float averageEloss = eloss / NumberOfSegs;
296 const std::vector<DigitizerUtility::EnergyDepositUnit>& ionization_points,
297 std::vector<DigitizerUtility::SignalPoint>& collection_points)
const {
298 LogDebug(
"Phase2TrackerDigitizerAlgorithm") <<
"enter drift ";
300 collection_points.reserve(ionization_points.size());
302 if (driftDir.
z() == 0.) {
303 LogWarning(
"Phase2TrackerDigitizerAlgorithm") <<
" pxlx: drift in z is zero ";
307 float TanLorenzAngleX = driftDir.
x();
308 float TanLorenzAngleY = 0.;
309 float dir_z = driftDir.
z();
311 float CosLorenzAngleY = 1.;
313 TanLorenzAngleY = driftDir.
y();
320 LogDebug(
"Phase2TrackerDigitizerAlgorithm")
321 <<
" Lorentz Tan " << TanLorenzAngleX <<
" " << TanLorenzAngleY <<
" " << CosLorenzAngleX <<
" "
322 << CosLorenzAngleY <<
" " << moduleThickness * TanLorenzAngleX <<
" " << driftDir;
324 for (
auto const&
val : ionization_points) {
326 float SegX =
val.x(), SegY =
val.y(), SegZ =
val.z();
333 float driftDistance = moduleThickness / 2. - (dir_z * SegZ);
335 if (driftDistance < 0.)
337 else if (driftDistance > moduleThickness)
338 driftDistance = moduleThickness;
341 float XDriftDueToMagField = driftDistance * TanLorenzAngleX;
342 float YDriftDueToMagField = driftDistance * TanLorenzAngleY;
345 float CloudCenterX = SegX + XDriftDueToMagField;
346 float CloudCenterY = SegY + YDriftDueToMagField;
355 float Sigma =
std::sqrt(driftLength / moduleThickness) *
Sigma0_ * moduleThickness / 0.0300;
362 float Sigma_x = Sigma / CosLorenzAngleX;
363 float Sigma_y = Sigma / CosLorenzAngleY;
366 float energyOnCollector =
val.energy();
373 energyOnCollector *=
exp(-1 * kValue * driftDistance / moduleThickness);
376 LogDebug(
"Phase2TrackerDigitizerAlgorithm")
377 <<
"Dift DistanceZ = " << driftDistance <<
" module thickness = " << moduleThickness
378 <<
" Start Energy = " <<
val.energy() <<
" Energy after loss= " << energyOnCollector;
382 collection_points.push_back(sp);
391 const size_t hitIndex,
392 const uint32_t tofBin,
394 const std::vector<DigitizerUtility::SignalPoint>& collection_points) {
401 LogDebug(
"Phase2TrackerDigitizerAlgorithm")
402 <<
" enter induce_signal, " << topol->
pitch().first <<
" " << topol->
pitch().second;
405 using hit_map_type = std::map<int, float, std::less<int> >;
406 hit_map_type hit_signal;
410 for (
auto const&
v : collection_points) {
411 float CloudCenterX =
v.position().x();
412 float CloudCenterY =
v.position().y();
417 LogDebug(
"Phase2TrackerDigitizerAlgorithm") <<
" cloud " <<
v.position().x() <<
" " <<
v.position().y() <<
" "
418 <<
v.sigma_x() <<
" " <<
v.sigma_y() <<
" " <<
v.amplitude();
439 int IPixRightUpX = static_cast<int>(std::floor(mp.
x()));
440 int IPixRightUpY = static_cast<int>(std::floor(mp.
y()));
441 LogDebug(
"Phase2TrackerDigitizerAlgorithm")
442 <<
" right-up " << PointRightUp <<
" " << mp.
x() <<
" " << mp.
y() <<
" " << IPixRightUpX <<
" " << IPixRightUpY;
445 int IPixLeftDownX = static_cast<int>(std::floor(mp.
x()));
446 int IPixLeftDownY = static_cast<int>(std::floor(mp.
y()));
447 LogDebug(
"Phase2TrackerDigitizerAlgorithm") <<
" left-down " << PointLeftDown <<
" " << mp.
x() <<
" " << mp.
y()
448 <<
" " << IPixLeftDownX <<
" " << IPixLeftDownY;
452 int numRows = topol->
nrows();
454 IPixRightUpX = numRows > IPixRightUpX ? IPixRightUpX : numRows - 1;
455 IPixRightUpY = numColumns > IPixRightUpY ? IPixRightUpY : numColumns - 1;
456 IPixLeftDownX = 0 < IPixLeftDownX ? IPixLeftDownX : 0;
457 IPixLeftDownY = 0 < IPixLeftDownY ? IPixLeftDownY : 0;
461 for (
int ix = IPixLeftDownX; ix <= IPixRightUpX; ++ix) {
462 float xLB, LowerBound;
465 if (ix == 0 ||
SigmaX == 0.) {
470 LowerBound = 1 -
calcQ((xLB - CloudCenterX) /
SigmaX);
473 float xUB, UpperBound;
474 if (ix == numRows - 1 ||
SigmaX == 0.) {
479 UpperBound = 1. -
calcQ((xUB - CloudCenterX) /
SigmaX);
481 float TotalIntegrationRange = UpperBound - LowerBound;
482 x.emplace(ix, TotalIntegrationRange);
487 for (
int iy = IPixLeftDownY; iy <= IPixRightUpY; ++iy) {
488 float yLB, LowerBound;
489 if (iy == 0 ||
SigmaY == 0.) {
494 LowerBound = 1. -
calcQ((yLB - CloudCenterY) /
SigmaY);
497 float yUB, UpperBound;
498 if (iy == numColumns - 1 ||
SigmaY == 0.) {
503 UpperBound = 1. -
calcQ((yUB - CloudCenterY) /
SigmaY);
506 float TotalIntegrationRange = UpperBound - LowerBound;
507 y.emplace(iy, TotalIntegrationRange);
511 for (
int ix = IPixLeftDownX; ix <= IPixRightUpX; ++ix) {
512 for (
int iy = IPixLeftDownY; iy <= IPixRightUpY; ++iy) {
513 float ChargeFraction =
Charge *
x[ix] *
y[iy];
515 if (ChargeFraction > 0.) {
519 hit_signal[chanFired] += ChargeFraction;
526 LogDebug(
"Phase2TrackerDigitizerAlgorithm")
527 <<
" pixel " << ix <<
" " << iy <<
" - "
528 <<
" " << chanFired <<
" " << ChargeFraction <<
" " << mp.
x() <<
" " << mp.
y() <<
" " << lp.
x() <<
" "
536 for (
auto const& hit_s : hit_signal) {
537 int chan = hit_s.first;
551 for (
auto&
s : theSignal) {
553 if ((
s.second.ampl() +
noise) < 0.)
569 int numRows = topol->
nrows();
571 for (
auto&
s : theSignal) {
572 float signalInElectrons =
s.second.ampl();
574 std::pair<int, int> hitChan;
582 s.second.set(signalInElectrons - signalInElectrons_Xtalk);
584 if (hitChan.first != 0) {
585 auto XtalkPrev = std::make_pair(hitChan.first - 1, hitChan.second);
590 if (hitChan.first < numRows - 1) {
591 auto XtalkNext = std::make_pair(hitChan.first + 1, hitChan.second);
597 for (
auto const&
l : signalNew) {
599 auto iter = theSignal.find(
chan);
600 if (iter != theSignal.end()) {
601 theSignal[
chan] +=
l.second.ampl();
619 int numRows = topol->
nrows();
621 int numberOfPixels = numRows * numColumns;
622 std::map<int, float, std::less<int> > otherPixels;
630 LogDebug(
"Phase2TrackerDigitizerAlgorithm")
633 << otherPixels.size();
636 for (
auto const& el : otherPixels) {
637 int iy = el.first / numRows;
638 if (iy < 0 || iy > numColumns - 1)
639 LogWarning(
"Phase2TrackerDigitizerAlgorithm") <<
" error in iy " << iy;
641 int ix = el.first - iy * numRows;
642 if (ix < 0 || ix > numRows - 1)
643 LogWarning(
"Phase2TrackerDigitizerAlgorithm") <<
" error in ix " << ix;
647 LogDebug(
"Phase2TrackerDigitizerAlgorithm")
648 <<
" Storing noise = " << el.first <<
" " << el.second <<
" " << ix <<
" " << iy <<
" " <<
chan;
650 if (theSignal[
chan] == 0)
665 float subdetEfficiency = 1.0;
670 uint32_t layerIndex = tTopo->
pxbLayer(detID);
674 uint32_t diskIndex = 2 * tTopo->
pxfDisk(detID) - tTopo->
pxfSide(detID);
679 LogDebug(
"Phase2TrackerDigitizerAlgorithm") <<
" enter pixel_inefficiency " << subdetEfficiency;
683 for (
auto&
s : theSignal) {
685 if (
rand > subdetEfficiency) {
716 const DetId& detId)
const {
731 float alpha2 =
std::pow(lorentzAngle, 2);
733 dir_x = -(lorentzAngle * Bfield.y() + alpha2 * Bfield.z() * Bfield.x());
734 dir_y = +(lorentzAngle * Bfield.x() - alpha2 * Bfield.z() * Bfield.y());
735 dir_z = -(1 + alpha2 *
std::pow(Bfield.z(), 2));
739 float alpha2_Endcap = 0.0;
740 float alpha2_Barrel = 0.0;
749 dir_z = -(1 + alpha2_Barrel *
std::pow(Bfield.z(), 2));
755 dir_z = -(1 + alpha2_Endcap *
std::pow(Bfield.z(), 2));
761 LogDebug(
"Phase2TrackerDigitizerAlgorithm") <<
" The drift direction in local coordinate is " << theDriftDirection;
762 return theDriftDirection;
771 for (
auto&
s : theSignal) {
772 std::pair<int, int> ip;
793 int Dead_detID = det_m.getParameter<
int>(
"Dead_detID");
795 if (detid == Dead_detID) {
805 for (
auto&
s : theSignal) {
806 std::pair<int, int> ip;
812 if (
Module ==
"whole" || (
Module ==
"tbmA" && ip.first >= 80 && ip.first <= 159) ||
813 (
Module ==
"tbmB" && ip.first <= 79))
827 for (
size_t id = 0;
id < disabledModules.size();
id++) {
828 if (detID == disabledModules[
id].DetID) {
830 badmodule = disabledModules[
id];
840 for (
auto&
s : theSignal)
845 std::vector<GlobalPixel> badrocpositions;
846 for (
size_t j = 0; j < static_cast<size_t>(ncol);
j++) {
849 for (
auto const&
p :
path) {
854 badrocpositions.push_back(global);
861 for (
auto&
s : theSignal) {
862 std::pair<int, int> ip;
868 for (
auto const&
p : badrocpositions) {
870 if (
p.row ==
k.getParameter<
int>(
"row") && ip.first ==
k.getParameter<
int>(
"row") &&
871 std::abs(ip.second -
p.col) <
k.getParameter<
int>(
"col")) {
882 auto& theSignal =
_signal[detId];
887 if (!inserted.second) {
888 throw cms::Exception(
"LogicError") <<
"Signal was already set for DetId " << detId;
894 std::map<int, DigitizerUtility::DigiSimInfo>& digi_map,
905 float theThresholdInE = 0.;
906 float theHIPThresholdInE = 0.;
941 for (
auto const&
s : theSignal) {
943 float signalInElectrons = sig_data.
ampl();
947 if (!info_list.empty())
948 hitInfo = std::max_element(info_list.begin(), info_list.end())->
second.get();
953 info.ot_bit = signalInElectrons > theHIPThresholdInE ?
true :
false;
956 float charge_frac =
l.first / signalInElectrons;
958 info.simInfoList.push_back({charge_frac,
l.second.get()});
961 digi_map.insert({
s.first,
info});
971 const int max_limit = 10;
982 if (temp_signal > kink_point)
983 temp_signal = std::floor((temp_signal - kink_point) / (
pow(2, dualslope_param - 1))) + kink_point;
986 LogTrace(
"Phase2TrackerDigitizerAlgorithm")
987 <<
" DetId " << detID <<
" signal_in_elec " << signal_in_elec <<
" threshold " <<
threshold
988 <<
" signal_above_thr " << signal_in_elec -
threshold <<
" temp conversion "
990 << temp_signal <<
" signal_in_adc " << signal_in_adc;
992 return signal_in_adc;