22 #include <boost/foreach.hpp>
29 typedef std::unordered_map<uint32_t, std::vector<std::pair<float, float>>>
IdHit_Map;
35 constexpr std::array<double, 4> occupancyGuesses = {{0.5, 0.2, 0.2, 0.8}};
40 const auto& dddConst =
geom->topology().dddConstants();
41 return (1 + dddConst.waferType(detid));
45 const std::vector<DetId>& ids =
geom->getValidDetIds();
46 valid.reserve(ids.size());
47 valid.insert(ids.begin(), ids.end());
52 const auto& topo =
geom->topology();
53 const auto& dddConst = topo.dddConstants();
55 if (dddConst.waferHexagon8() || dddConst.tileTrapezoid()) {
58 int subdet(
DetId(simId).subdetId()),
layer, cell,
sec, subsec, zp;
62 auto recoLayerCell = dddConst.simToReco(cell,
layer,
sec, topo.detectorType());
63 cell = recoLayerCell.first;
64 layer = recoLayerCell.second;
65 if (
layer < 0 || cell < 0) {
77 const std::unordered_set<DetId>& validIds,
78 const float minCharge,
79 const float maxCharge) {
82 "PHGCSimAccumulator bit pattern needs to updated");
84 "PHGCSimAccumulator bit pattern needs to updated");
85 const float minPackChargeLog = minCharge > 0.f ?
std::log(minCharge) : -2;
86 const float maxPackChargeLog =
std::log(maxCharge);
89 simResult.
reserve(simData.size());
91 for (
const auto&
id : validIds) {
92 auto found = simData.find(
id);
93 if (
found == simData.end())
99 const std::vector<float>& accCharge_inthis_bx = accCharge_across_bxs[iSample];
100 const std::vector<float>& timing_inthis_bx = timing_across_bxs[iSample];
101 std::vector<unsigned short> vc, vt;
102 size_t nhits = accCharge_inthis_bx.size();
104 for (
size_t ihit = 0; ihit <
nhits; ++ihit) {
105 if (accCharge_inthis_bx[ihit] > minCharge) {
124 const float minCharge,
125 const float maxCharge,
127 const std::array<float, 3>& tdcForToAOnset,
128 const bool minbiasFlag,
129 std::unordered_map<uint32_t, bool>& hitOrder_monitor,
130 const unsigned int thisBx) {
131 const float minPackChargeLog = minCharge > 0.f ?
std::log(minCharge) : -2;
132 const float maxPackChargeLog =
std::log(maxCharge);
134 for (
const auto& detIdIndexHitInfo : simAccumulator) {
135 unsigned int detId = detIdIndexHitInfo.detId();
137 auto simIt = simData.emplace(detId,
HGCCellInfo()).first;
138 size_t nhits = detIdIndexHitInfo.nhits();
140 hitOrder_monitor[detId] =
false;
142 unsigned short iSample = detIdIndexHitInfo.sampleIndex();
144 const auto& unsigned_charge_array = detIdIndexHitInfo.chargeArray();
145 const auto& unsigned_time_array = detIdIndexHitInfo.timeArray();
147 float p_charge, p_time;
148 unsigned short unsigned_charge, unsigned_time;
150 for (
size_t ihit = 0; ihit <
nhits; ++ihit) {
156 (simIt->second).hit_info[0][iSample] += p_charge;
157 if (iSample == (
unsigned short)thisBx) {
158 if (hitRefs_bx0[detId].
empty()) {
159 hitRefs_bx0[detId].emplace_back(p_charge, p_time);
161 if (p_time < hitRefs_bx0[detId].back().
second) {
163 hitRefs_bx0[detId].
end(),
164 std::make_pair(0.
f, p_time),
165 [](
const auto&
i,
const auto&
j) {
return i.second <
j.second; });
167 auto insertedPos = findPos;
168 if (findPos == hitRefs_bx0[detId].begin()) {
169 insertedPos = hitRefs_bx0[detId].emplace(insertedPos, p_charge, p_time);
171 auto prevPos = findPos - 1;
172 if (prevPos->second == p_time) {
173 prevPos->first = prevPos->first + p_charge;
174 insertedPos = prevPos;
175 }
else if (prevPos->second < p_time) {
176 insertedPos = hitRefs_bx0[detId].emplace(findPos, (prevPos)->
first + p_charge, p_time);
180 for (
auto step = insertedPos;
step != hitRefs_bx0[detId].end(); ++
step) {
181 if (
step != insertedPos)
182 step->first += p_charge;
185 hitOrder_monitor[detId] =
true;
187 }
else if (p_time == hitRefs_bx0[detId].back().second) {
188 hitRefs_bx0[detId].back().first += p_charge;
189 }
else if (p_time > hitRefs_bx0[detId].back().
second) {
190 hitRefs_bx0[detId].emplace_back(hitRefs_bx0[detId].back().
first + p_charge, p_time);
199 for (
const auto& hitmapIterator : hitRefs_bx0) {
200 unsigned int detectorId = hitmapIterator.first;
201 auto simIt = simData.emplace(detectorId,
HGCCellInfo()).first;
202 const bool orderChanged = hitOrder_monitor[detectorId];
203 int waferThickness = getCellThickness(
geom, detectorId);
204 float cell_threshold = tdcForToAOnset[waferThickness - 1];
205 const auto& hitRec = hitmapIterator.second;
206 float accChargeForToA(0.
f), fireTDC(0.
f);
208 hitRec.begin(), hitRec.end(), std::make_pair(cell_threshold, 0.
f), [](
const auto&
i,
const auto&
j) {
209 return i.first <
j.first;
212 if (aboveThrPos == hitRec.end()) {
213 accChargeForToA = hitRec.back().first;
215 }
else if (hitRec.end() - aboveThrPos > 0 || orderChanged) {
216 accChargeForToA = aboveThrPos->first;
217 fireTDC = aboveThrPos->second;
218 if (aboveThrPos - hitRec.begin() >= 1) {
219 const auto& belowThrPos = aboveThrPos - 1;
220 float chargeBeforeThr = belowThrPos->first;
221 float timeBeforeThr = belowThrPos->second;
222 float deltaQ = accChargeForToA - chargeBeforeThr;
223 float deltaTOF = fireTDC - timeBeforeThr;
224 fireTDC = (cell_threshold - chargeBeforeThr) * deltaTOF / deltaQ + timeBeforeThr;
227 (simIt->second).hit_info[1][9] = fireTDC;
236 refSpeed_(0.1 *
CLHEP::c_light),
237 averageOccupancies_(occupancyGuesses),
251 std::unordered_set<DetId>().swap(
validIds_);
258 .getParameter<std::vector<double>>(
"values");
259 for (
double cce :
temp) {
260 cce_.emplace_back(cce);
263 std::vector<float>().swap(
cce_);
299 auto simRecord = std::make_unique<PHGCSimAccumulator>();
302 saveSimHitAccumulator_forPreMix(
309 auto digiResult = std::make_unique<HGCalDigiCollection>();
311 edm::LogVerbatim(
"HGCDigitizer") <<
"HGCDigitizer:: finalize event - produced " << digiResult->size()
325 CLHEP::HepRandomEngine* hre) {
330 if (!
hits.isValid()) {
332 <<
" collection of g4SimHits";
340 throw cms::Exception(
"BadConfiguration") <<
"HGCDigitizer is not producing EE, FH, or BH digis!";
349 if (!
hits.isValid()) {
358 throw cms::Exception(
"BadConfiguration") <<
"HGCDigitizer is not producing EE, FH, or BH digis!";
365 CLHEP::HepRandomEngine* hre) {
369 if (!
hits.isValid()) {
377 throw cms::Exception(
"BadConfiguration") <<
"HGCDigitizer is not producing EE, FH, or BH digis!";
384 CLHEP::HepRandomEngine* hre) {
389 if (!
hits.isValid()) {
398 throw cms::Exception(
"BadConfiguration") <<
"HGCDigitizer is not producing EE, FH, or BH digis!";
406 CLHEP::HepRandomEngine* hre) {
413 int nchits = (
int)
hits->size();
414 int count_thisbx = 0;
415 std::vector<HGCCaloHitTuple_t> hitRefs;
416 hitRefs.reserve(nchits);
417 for (
int i = 0;
i < nchits; ++
i) {
418 const auto& the_hit =
hits->at(
i);
419 DetId id = simToReco(
geom, the_hit.id());
421 if (
id.rawId() != 0) {
422 hitRefs.emplace_back(
i,
id.rawId(), (
float)the_hit.time());
427 nchits = hitRefs.size();
428 for (
int i = 0;
i < nchits; ++
i) {
429 const int hitidx = std::get<0>(hitRefs[
i]);
430 const uint32_t
id = std::get<1>(hitRefs[
i]);
437 const float toa = std::get<2>(hitRefs[
i]);
441 const float dist2center(getPositionDistance(
geom,
id));
443 const int itime = std::floor(tof /
bxTime_) + 9;
445 if (itime < 0 || itime > (
int)
maxBx_)
448 if (itime >= (
int)(
maxBx_ + 1))
451 int waferThickness = getCellThickness(
geom,
id);
456 }
else if (tof > std::get<2>(
PhitRefs_bx0[
id].back())) {
458 }
else if (tof == std::get<2>(
PhitRefs_bx0[
id].back())) {
466 [](
const auto&
i,
const auto&
j) {
return std::get<2>(
i) <= std::get<2>(
j); });
468 auto insertedPos = findPos;
470 if (tof == std::get<2>(*(findPos - 1))) {
471 std::get<0>(*(findPos - 1)) +=
charge;
472 std::get<1>(*(findPos - 1)) +=
charge;
484 if (
step != insertedPos)
488 if (std::get<1>(*
step) > tdcForToAOnset[waferThickness - 1] &&
494 [](
const auto&
i,
const auto&
j) {
return std::get<2>(
i) < std::get<2>(
j); }) -
497 std::get<1>(*stepEnd) +=
charge;
509 for (
const auto& hit_timestamp :
PhitRefs_bx0[detectorId]) {
510 (simHitIt->second).PUhit_info[1][
thisBx_].push_back(std::get<2>(hit_timestamp));
511 (simHitIt->second).PUhit_info[0][
thisBx_].push_back(std::get<0>(hit_timestamp));
517 (simHitIt->second).PUhit_info[1][9].push_back(0.0);
518 (simHitIt->second).PUhit_info[0][9].push_back(0.0);
528 CLHEP::HepRandomEngine* hre) {
538 int nchits = (
int)
hits->size();
540 std::vector<HGCCaloHitTuple_t> hitRefs;
541 hitRefs.reserve(nchits);
542 for (
int i = 0;
i < nchits; ++
i) {
543 const auto& the_hit =
hits->at(
i);
544 DetId id = simToReco(
geom, the_hit.id());
547 edm::LogVerbatim(
"HGCDigitizer") <<
"HGCDigitizer::i/p " << std::hex << the_hit.id() <<
" o/p " <<
id.rawId()
551 if (0 !=
id.rawId()) {
552 hitRefs.emplace_back(
i,
id.rawId(), (
float)the_hit.time());
558 nchits = hitRefs.size();
559 for (
int i = 0;
i < nchits; ++
i) {
560 const int hitidx = std::get<0>(hitRefs[
i]);
561 const uint32_t
id = std::get<1>(hitRefs[
i]);
572 const float toa = std::get<2>(hitRefs[
i]);
577 const float dist2center(getPositionDistance(
geom,
id));
582 const int itime = std::floor(tof /
bxTime_) + 9;
588 if (itime < 0 || itime > (
int)
maxBx_)
592 if (itime >= (
int)simHitIt->second.hit_info[0].size())
595 (simHitIt->second).hit_info[0][itime] +=
charge;
599 int waferThickness = getCellThickness(
geom,
id);
600 bool orderChanged =
false;
608 std::vector<std::pair<float, float>>::iterator findPos =
611 std::pair<float, float>(0.
f, tof),
612 [](
const auto&
i,
const auto&
j) {
return i.second <=
j.second; });
614 std::vector<std::pair<float, float>>::iterator insertedPos = findPos;
615 if (findPos->second == tof) {
622 ? std::pair<float, float>(
charge, tof)
623 : std::pair<float, float>((findPos - 1)->
first +
charge, tof));
629 if (
step != insertedPos)
632 if (
step->first > tdcForToAOnset[waferThickness - 1] &&
step->second !=
hitRefs_bx0[
id].back().second) {
635 std::pair<float, float>(0.
f,
step->second),
636 [](
const auto&
i,
const auto&
j) { return i.second < j.second; }) -
647 if (
hitRefs_bx0[
id].back().first <= tdcForToAOnset[waferThickness - 1]) {
654 if (weightToAbyEnergy)
655 (simHitIt->second).hit_info[1][itime] +=
charge * tof;
656 else if (accChargeForToA > tdcForToAOnset[waferThickness - 1] &&
657 ((simHitIt->second).hit_info[1][itime] == 0 || orderChanged ==
true)) {
663 float deltaQ = accChargeForToA - chargeBeforeThr;
664 float deltaTOF = fireTDC - tofchargeBeforeThr;
665 fireTDC = (tdcForToAOnset[waferThickness - 1] - chargeBeforeThr) * deltaTOF / deltaQ + tofchargeBeforeThr;
667 (simHitIt->second).hit_info[1][itime] = fireTDC;
709 throw cms::Exception(
"BadConfiguration") <<
"HGCDigitizer is not producing EE, FH, or BH digis!";
723 it->second.hit_info[0].fill(0.);
724 it->second.hit_info[1].fill(0.);
750 const double tol(0.5);
752 for (
const auto& digi : *(digis)) {
753 const DetId&
id = digi.id();
755 double r = global.
perp();
759 bool ok = ((
r >= rrange.first) && (
r <= rrange.second) && (
z >=
zrange.first) && (
z <=
zrange.second));
760 std::string ck = (((
r < rrange.first - tol) || (
r > rrange.second + tol) || (
z <
zrange.first - tol) ||
762 ?
"***** ERROR *****"
765 if ((!
ok) || (!
val)) {
768 << rrange.first <<
":" << rrange.second <<
" Z " <<
z <<
":" <<
zrange.first
769 <<
":" <<
zrange.second <<
" Flag " <<
ok <<
":" <<
val <<
" " << ck;
772 << rrange.first <<
":" << rrange.second <<
" Z " <<
z <<
":" <<
zrange.first
773 <<
":" <<
zrange.second <<
" Flag " <<
ok <<
":" <<
val <<
" " << ck;
776 << rrange.first <<
":" << rrange.second <<
" Z " <<
z <<
":" <<
zrange.first
777 <<
":" <<
zrange.second <<
" Flag " <<
ok <<
":" <<
val <<
" " << ck;
780 <<
"Check " << std::hex <<
id.rawId() <<
std::dec <<
" " <<
id.det() <<
":" <<
id.subdetId() <<
" "
781 << global <<
" R " <<
r <<
":" << rrange.first <<
":" << rrange.second <<
" Z " <<
z <<
":"
782 <<
zrange.first <<
":" <<
zrange.second <<
" Flag " <<
ok <<
":" <<
val <<
" " << ck;