20 #include <boost/foreach.hpp>
25 using namespace hgc_digi;
27 typedef std::unordered_map<uint32_t, std::vector<std::pair<float, float>>>
IdHit_Map;
33 constexpr std::array<double, 4> occupancyGuesses = {{0.5, 0.2, 0.2, 0.8}};
39 return (1 + dddConst.waferType(detid));
42 void getValidDetIds(
const HGCalGeometry* geom, std::unordered_set<DetId>& valid) {
44 valid.reserve(ids.size());
45 valid.insert(ids.begin(), ids.end());
53 if (dddConst.waferHexagon8() || dddConst.tileTrapezoid()) {
54 result =
DetId(simId);
56 int subdet(
DetId(simId).subdetId()),
layer, cell, sec, subsec, zp;
60 auto recoLayerCell = dddConst.simToReco(cell, layer, sec, topo.detectorType());
61 cell = recoLayerCell.first;
62 layer = recoLayerCell.second;
63 if (layer < 0 || cell < 0) {
75 const std::unordered_set<DetId>& validIds,
76 const float minCharge,
77 const float maxCharge) {
80 "PHGCSimAccumulator bit pattern needs to updated");
82 "PHGCSimAccumulator bit pattern needs to updated");
83 const float minPackChargeLog = minCharge > 0.f ?
std::log(minCharge) : -2;
84 const float maxPackChargeLog =
std::log(maxCharge);
87 simResult.
reserve(simData.size());
89 for (
const auto&
id : validIds) {
90 auto found = simData.find(
id);
91 if (
found == simData.end())
97 const std::vector<float>& accCharge_inthis_bx = accCharge_across_bxs[iSample];
98 const std::vector<float>& timing_inthis_bx = timing_across_bxs[iSample];
99 std::vector<unsigned short> vc, vt;
100 size_t nhits = accCharge_inthis_bx.size();
102 for (
size_t ihit = 0; ihit <
nhits; ++ihit) {
103 if (accCharge_inthis_bx[ihit] > minCharge) {
106 unsigned short t =
logintpack::pack16log(timing_inthis_bx[ihit], minPackChargeLog, maxPackChargeLog, base);
122 const float minCharge,
123 const float maxCharge,
125 const std::array<float, 3>& tdcForToAOnset,
126 const bool minbiasFlag,
127 std::unordered_map<uint32_t, bool>& hitOrder_monitor,
128 const unsigned int thisBx) {
129 const float minPackChargeLog = minCharge > 0.f ?
std::log(minCharge) : -2;
130 const float maxPackChargeLog =
std::log(maxCharge);
132 for (
const auto& detIdIndexHitInfo : simAccumulator) {
133 unsigned int detId = detIdIndexHitInfo.detId();
135 auto simIt = simData.emplace(detId,
HGCCellInfo()).first;
136 size_t nhits = detIdIndexHitInfo.nhits();
138 hitOrder_monitor[detId] =
false;
140 unsigned short iSample = detIdIndexHitInfo.sampleIndex();
142 const auto& unsigned_charge_array = detIdIndexHitInfo.chargeArray();
143 const auto& unsigned_time_array = detIdIndexHitInfo.timeArray();
145 float p_charge, p_time;
146 unsigned short unsigned_charge, unsigned_time;
148 for (
size_t ihit = 0; ihit <
nhits; ++ihit) {
154 (simIt->second).hit_info[0][iSample] += p_charge;
155 if (iSample == (
unsigned short)thisBx) {
156 if (hitRefs_bx0[detId].
empty()) {
157 hitRefs_bx0[detId].emplace_back(p_charge, p_time);
159 if (p_time < hitRefs_bx0[detId].back().
second) {
161 hitRefs_bx0[detId].
end(),
162 std::make_pair(0.
f, p_time),
163 [](
const auto&
i,
const auto&
j) {
return i.second <
j.second; });
165 auto insertedPos = findPos;
166 if (findPos == hitRefs_bx0[detId].
begin()) {
167 insertedPos = hitRefs_bx0[detId].emplace(insertedPos, p_charge, p_time);
169 auto prevPos = findPos - 1;
170 if (prevPos->second == p_time) {
171 prevPos->first = prevPos->first + p_charge;
172 insertedPos = prevPos;
173 }
else if (prevPos->second < p_time) {
174 insertedPos = hitRefs_bx0[detId].emplace(findPos, (prevPos)->
first + p_charge, p_time);
178 for (
auto step = insertedPos;
step != hitRefs_bx0[detId].end(); ++
step) {
179 if (
step != insertedPos)
180 step->first += p_charge;
183 hitOrder_monitor[detId] =
true;
185 }
else if (p_time == hitRefs_bx0[detId].back().second) {
186 hitRefs_bx0[detId].back().first += p_charge;
187 }
else if (p_time > hitRefs_bx0[detId].back().
second) {
188 hitRefs_bx0[detId].emplace_back(hitRefs_bx0[detId].back().
first + p_charge, p_time);
197 for (
const auto& hitmapIterator : hitRefs_bx0) {
198 unsigned int detectorId = hitmapIterator.first;
199 auto simIt = simData.emplace(detectorId,
HGCCellInfo()).first;
200 const bool orderChanged = hitOrder_monitor[detectorId];
201 int waferThickness = getCellThickness(geom, detectorId);
202 float cell_threshold = tdcForToAOnset[waferThickness - 1];
203 const auto& hitRec = hitmapIterator.second;
204 float accChargeForToA(0.
f), fireTDC(0.
f);
206 hitRec.begin(), hitRec.end(), std::make_pair(cell_threshold, 0.
f), [](
const auto&
i,
const auto&
j) {
207 return i.first <
j.first;
210 if (aboveThrPos == hitRec.end()) {
211 accChargeForToA = hitRec.back().first;
213 }
else if (hitRec.end() - aboveThrPos > 0 || orderChanged) {
214 accChargeForToA = aboveThrPos->first;
215 fireTDC = aboveThrPos->second;
216 if (aboveThrPos - hitRec.begin() >= 1) {
217 const auto& belowThrPos = aboveThrPos - 1;
218 float chargeBeforeThr = belowThrPos->first;
219 float timeBeforeThr = belowThrPos->second;
220 float deltaQ = accChargeForToA - chargeBeforeThr;
221 float deltaTOF = fireTDC - timeBeforeThr;
222 fireTDC = (cell_threshold - chargeBeforeThr) * deltaTOF / deltaQ + timeBeforeThr;
225 (simIt->second).hit_info[1][9] = fireTDC;
235 refSpeed_(0.1 * CLHEP::c_light),
236 averageOccupancies_(occupancyGuesses),
256 .getParameter<std::vector<double>>(
"values");
257 for (
double cce :
temp) {
258 cce_.emplace_back(cce);
284 throw cms::Exception(
"BadConfiguration") <<
"HGCDigitizer is not producing EE, FH, or BH digis!";
319 auto simRecord = std::make_unique<PHGCSimAccumulator>();
322 saveSimHitAccumulator_forPreMix(
329 auto digiResult = std::make_unique<HGCalDigiCollection>();
331 edm::LogVerbatim(
"HGCDigitizer") <<
"HGCDigitizer:: finalize event - produced " << digiResult->size()
345 CLHEP::HepRandomEngine* hre) {
352 <<
" collection of g4SimHits";
360 throw cms::Exception(
"BadConfiguration") <<
"HGCDigitizer is not producing EE, FH, or BH digis!";
378 throw cms::Exception(
"BadConfiguration") <<
"HGCDigitizer is not producing EE, FH, or BH digis!";
385 CLHEP::HepRandomEngine* hre) {
397 throw cms::Exception(
"BadConfiguration") <<
"HGCDigitizer is not producing EE, FH, or BH digis!";
404 CLHEP::HepRandomEngine* hre) {
418 throw cms::Exception(
"BadConfiguration") <<
"HGCDigitizer is not producing EE, FH, or BH digis!";
426 CLHEP::HepRandomEngine* hre) {
433 int nchits = (int)hits->size();
434 int count_thisbx = 0;
435 std::vector<HGCCaloHitTuple_t> hitRefs;
436 hitRefs.reserve(nchits);
437 for (
int i = 0;
i < nchits; ++
i) {
438 const auto& the_hit = hits->at(
i);
439 DetId id = simToReco(geom, the_hit.id());
441 if (
id.rawId() != 0) {
442 hitRefs.emplace_back(
i,
id.rawId(), (
float)the_hit.time());
447 nchits = hitRefs.size();
448 for (
int i = 0;
i < nchits; ++
i) {
449 const int hitidx = std::get<0>(hitRefs[
i]);
450 const uint32_t
id = std::get<1>(hitRefs[
i]);
457 const float toa = std::get<2>(hitRefs[
i]);
461 const float dist2center(getPositionDistance(geom,
id));
463 const int itime = std::floor(tof /
bxTime_) + 9;
465 if (itime < 0 || itime > (
int)
maxBx_)
468 if (itime >= (
int)(maxBx_ + 1))
471 int waferThickness = getCellThickness(geom,
id);
476 }
else if (tof > std::get<2>(
PhitRefs_bx0[
id].back())) {
478 }
else if (tof == std::get<2>(
PhitRefs_bx0[
id].back())) {
486 [](
const auto&
i,
const auto&
j) {
return std::get<2>(
i) <= std::get<2>(
j); });
488 auto insertedPos = findPos;
490 if (tof == std::get<2>(*(findPos - 1))) {
491 std::get<0>(*(findPos - 1)) +=
charge;
492 std::get<1>(*(findPos - 1)) +=
charge;
498 :
hit_timeStamp(charge, charge + std::get<1>(*(findPos - 1)), tof));
504 if (
step != insertedPos)
508 if (std::get<1>(*
step) > tdcForToAOnset[waferThickness - 1] &&
514 [](
const auto&
i,
const auto&
j) {
return std::get<2>(
i) < std::get<2>(
j); }) -
517 std::get<1>(*stepEnd) +=
charge;
529 for (
const auto& hit_timestamp : PhitRefs_bx0[detectorId]) {
530 (simHitIt->second).PUhit_info[1][
thisBx_].
push_back(std::get<2>(hit_timestamp));
531 (simHitIt->second).PUhit_info[0][
thisBx_].
push_back(std::get<0>(hit_timestamp));
537 (simHitIt->second).PUhit_info[1][9].
push_back(0.0);
538 (simHitIt->second).PUhit_info[0][9].
push_back(0.0);
541 PhitRefs_bx0.clear();
548 CLHEP::HepRandomEngine* hre) {
558 int nchits = (int)hits->size();
560 std::vector<HGCCaloHitTuple_t> hitRefs;
561 hitRefs.reserve(nchits);
562 for (
int i = 0;
i < nchits; ++
i) {
563 const auto& the_hit = hits->at(
i);
564 DetId id = simToReco(geom, the_hit.id());
567 edm::LogVerbatim(
"HGCDigitizer") <<
"HGCDigitizer::i/p " << std::hex << the_hit.id() <<
" o/p " <<
id.rawId()
571 if (0 !=
id.rawId()) {
572 hitRefs.emplace_back(
i,
id.rawId(), (
float)the_hit.time());
578 nchits = hitRefs.size();
579 for (
int i = 0;
i < nchits; ++
i) {
580 const int hitidx = std::get<0>(hitRefs[
i]);
581 const uint32_t
id = std::get<1>(hitRefs[
i]);
592 const float toa = std::get<2>(hitRefs[
i]);
597 const float dist2center(getPositionDistance(geom,
id));
602 const int itime = std::floor(tof /
bxTime_) + 9;
608 if (itime < 0 || itime > (
int)
maxBx_)
612 if (itime >= (
int)simHitIt->second.hit_info[0].size())
615 (simHitIt->second).hit_info[0][itime] += charge;
619 int waferThickness = getCellThickness(geom,
id);
620 bool orderChanged =
false;
628 std::vector<std::pair<float, float>>::iterator findPos =
631 std::pair<float, float>(0.
f, tof),
632 [](
const auto&
i,
const auto&
j) {
return i.second <=
j.second; });
634 std::vector<std::pair<float, float>>::iterator insertedPos = findPos;
635 if (findPos->second == tof) {
642 ? std::pair<float, float>(charge, tof)
643 : std::pair<float, float>((findPos - 1)->
first + charge, tof));
649 if (
step != insertedPos)
652 if (
step->first > tdcForToAOnset[waferThickness - 1] &&
step->second !=
hitRefs_bx0[
id].back().second) {
655 std::pair<float, float>(0.
f,
step->second),
656 [](
const auto&
i,
const auto&
j) {
return i.second <
j.second; }) -
659 stepEnd->first += charge;
667 if (
hitRefs_bx0[
id].back().first <= tdcForToAOnset[waferThickness - 1]) {
674 if (weightToAbyEnergy)
675 (simHitIt->second).hit_info[1][itime] +=
charge * tof;
676 else if (accChargeForToA > tdcForToAOnset[waferThickness - 1] &&
677 ((simHitIt->second).hit_info[1][itime] == 0 || orderChanged ==
true)) {
683 float deltaQ = accChargeForToA - chargeBeforeThr;
684 float deltaTOF = fireTDC - tofchargeBeforeThr;
685 fireTDC = (tdcForToAOnset[waferThickness - 1] - chargeBeforeThr) * deltaTOF / deltaQ + tofchargeBeforeThr;
687 (simHitIt->second).hit_info[1][itime] = fireTDC;
716 it->second.hit_info[0].fill(0.);
717 it->second.hit_info[1].fill(0.);
743 const double tol(0.5);
745 for (
const auto& digi : *(digis)) {
746 const DetId&
id = digi.id();
748 double r = global.
perp();
752 bool ok = ((r >= rrange.first) && (r <= rrange.second) && (z >= zrange.first) && (z <= zrange.second));
753 std::string ck = (((r < rrange.first - tol) || (r > rrange.second + tol) || (z < zrange.first - tol) ||
754 (z > zrange.second + tol))
755 ?
"***** ERROR *****"
758 if ((!ok) || (!val)) {
761 << rrange.first <<
":" << rrange.second <<
" Z " << z <<
":" << zrange.first
762 <<
":" << zrange.second <<
" Flag " << ok <<
":" << val <<
" " << ck;
765 << rrange.first <<
":" << rrange.second <<
" Z " << z <<
":" << zrange.first
766 <<
":" << zrange.second <<
" Flag " << ok <<
":" << val <<
" " << ck;
769 << rrange.first <<
":" << rrange.second <<
" Z " << z <<
":" << zrange.first
770 <<
":" << zrange.second <<
" Flag " << ok <<
":" << val <<
" " << ck;
773 <<
"Check " << std::hex <<
id.rawId() <<
std::dec <<
" " <<
id.det() <<
":" <<
id.subdetId() <<
" "
774 << global <<
" R " << r <<
":" << rrange.first <<
":" << rrange.second <<
" Z " << z <<
":"
775 << zrange.first <<
":" << zrange.second <<
" Flag " << ok <<
":" << val <<
" " << ck;
int bunchCrossing() const
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
Log< level::Info, true > LogVerbatim
const CaloSubdetectorGeometry * getSubdetectorGeometry(const DetId &id) const
access the subdetector geometry for the given subdetector directly
void emplace_back(unsigned int detId, unsigned short sampleIndex, const std::vector< unsigned short > &accCharge, const std::vector< unsigned short > &timing)
T getUntrackedParameter(std::string const &, T const &) const
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
static std::vector< std::string > checklist log
std::vector< float > cce_
const edm::EventSetup & c
void finalizeEvent(edm::Event &e, edm::EventSetup const &c, CLHEP::HepRandomEngine *hre)
std::string hitCollection_
std::unique_ptr< HGCDigitizerBase > theDigitizer_
uint16_t *__restrict__ id
void resetSimHitDataAccumulator()
const edm::ESGetToken< CaloGeometry, CaloGeometryRecord > geomToken_
bool valid(const DetId &id) const override
Is this a valid cell id.
std::unordered_map< uint32_t, HGCCellInfo > HGCSimHitDataAccumulator
__host__ __device__ constexpr RandomIt upper_bound(RandomIt first, RandomIt last, const T &value, Compare comp={})
void initializeEvent(edm::Event const &e, edm::EventSetup const &c)
actions at the start/end of event
static constexpr unsigned dataMask
double unpack16log(int16_t i, double lmin, double lmax, uint16_t base=32768)
Log< level::Error, false > LogError
const HGCalGeometry * gHGCal_
void swap(Association< C > &lhs, Association< C > &rhs)
constexpr std::array< uint8_t, layerIndexSize > layer
std::string digiCollection_
bool getData(T &iHolder) const
U second(std::pair< T, U > const &p)
std::pair< double, double > rangeR(double z, bool reco) const
static const unsigned int maxBx_
edm::ESWatcher< CaloGeometryRecord > geomWatcher_
std::unordered_map< uint32_t, std::vector< hit_timeStamp > > hitRec_container
static constexpr unsigned sampleOffset
std::pair< double, double > rangeZ(bool reco) const
std::unordered_map< uint32_t, std::vector< std::tuple< float, float, float > > > PhitRefs_bx0
const HGCalTopology & topology() const
std::unordered_map< uint32_t, bool > hitOrder_monitor
Abs< T >::type abs(const T &t)
std::array< HGCSimDataCollection, nSamples > PUSimHitData
std::unordered_set< DetId > validIds_
constexpr size_t nSamples
static const unsigned int thisBx_
bool getByLabel(InputTag const &tag, Handle< PROD > &result) const
std::unordered_map< uint32_t, std::vector< std::pair< float, float > > > IdHit_Map
Log< level::Info, false > LogInfo
void reserve(size_t size)
double premixStage1MinCharge_
void checkPosition(const HGCalDigiCollection *digis) const
const HGCalDDDConstants & dddConstants() const
T getParameter(std::string const &) const
const std::vector< DetId > & getValidDetIds(DetId::Detector det=DetId::Detector(0), int subdet=0) const override
Get a list of valid detector ids (for the given subdetector)
bool check(const edm::EventSetup &iSetup)
deadvectors[0] push_back({0.0175431, 0.538005, 6.80997, 13.29})
std::array< double, 4 > averageOccupancies_
void accumulate(edm::Event const &e, edm::EventSetup const &c, CLHEP::HepRandomEngine *hre)
handle SimHit accumulation
GlobalPoint getPosition(const DetId &id, bool debug=false) const
bool getByLabel(edm::InputTag const &tag, edm::Handle< T > &result) const
std::unordered_map< uint32_t, std::vector< std::pair< float, float > > > hitRefs_bx0
HGCDigitizer(const edm::ParameterSet &ps, edm::ConsumesCollector &iC)
std::tuple< float, float, float > hit_timeStamp
std::unique_ptr< hgc::HGCSimHitDataAccumulator > simHitAccumulator_
static bool orderByDetIdThenTime(const HGCCaloHitTuple_t &a, const HGCCaloHitTuple_t &b)
void accumulate_forPreMix(edm::Event const &e, edm::EventSetup const &c, CLHEP::HepRandomEngine *hre)
static constexpr unsigned energyMask
int16_t pack16log(double x, double lmin, double lmax, uint16_t base=32768)
double premixStage1MaxCharge_
std::unique_ptr< hgc::HGCPUSimHitDataAccumulator > pusimHitAccumulator_
std::string digiCollection()
tuple size
Write out results.
static void unpackHexagonIndex(const uint32_t &idx, int &subdet, int &z, int &lay, int &wafer, int &celltyp, int &cell)
static constexpr unsigned sampleMask
std::unordered_map< uint32_t, HGCCellHitInfo > HGCPUSimHitDataAccumulator