33#include "CLHEP/Random/Randomize.h"
34#include "CLHEP/Random/RandomEngine.h"
42using CLHEP::RandGaussQ;
43using CLHEP::RandPoissonT;
44using CLHEP::RandGeneral;
47 const std::string& name,
48 const IInterface* parent)
75 ATH_MSG_INFO(
"No photostatistics effect will be simulated");
92 ATH_MSG_INFO(
" In case of pileup, the trigger time subtraction is done in PileUpSvc");
93 ATH_MSG_INFO(
" => TileHitVecToCnt will not apply Trigger Time ");
112 <<
"'; therefore set HitTimeFlag to 2");
125 ATH_MSG_INFO(
"Minimal hit time will be used as trigger time"
126 <<
" with random additional shift between 0 and " << -
m_triggerTime <<
" ns");
129 ATH_MSG_INFO(
"Average time will be calculated in every event");
137 ATH_MSG_INFO(
"Time of all hits will be preserved during copy");
149 for (
int ros = 3; ros < 5; ++ros) {
150 for (
int drawer = 0; drawer < 64; ++drawer) {
175 ATH_MSG_DEBUG(
"TileHitVecToCntTool initialization completed");
177 return StatusCode::SUCCESS;
194 for (std::unique_ptr<TileHit>& hit :
m_allHits) {
212 return StatusCode::SUCCESS;
218 ATH_MSG_DEBUG(
"TileHitVecToCntTool prepareEvent initialization started");
227 return StatusCode::SUCCESS;
235 for (; inpItr != end; ++inpItr) {
237 const TileHit * cinp = &(*inpItr);
239 eHitTot += cinp->
energy();
242 hits->push_back(pHit);
245 if (msgLvl(MSG::VERBOSE)) {
246 int hitsize = cinp->
size();
249 for (
int i = 0; i < hitsize; ++i) {
258 eHitTot += eHit - cinp->
energy();
260 msg(MSG::VERBOSE) <<
" nHit=" << nHit
264 <<
" Copy hit: ener=";
265 for (
int i = 0; i < hitsize; ++i)
266 msg(MSG::VERBOSE) << cinp->
energy(i) <<
" ";
267 msg(MSG::VERBOSE) <<
"time=";
268 for (
int i = 0; i < hitsize; ++i)
269 msg(MSG::VERBOSE) << cinp->
time(i) <<
" ";
277 std::vector<std::unique_ptr<TileHit>>& allHits,
278 std::vector<std::unique_ptr<TileHit>>& allHits_DigiHSTruth,
279 int& nHit,
double& eHitTot,
bool isSignal)
const {
289 for (; inpItr != end; ++inpItr) {
291 const TileHit * cinp = &(*inpItr);
295 int side = std::max(0,
m_tileTBID->type(hit_id));
303 m_tileID->get_hash(hit_id, hit_idhash, &pmt_context);
306 if (hit_idhash >= allHits.size()) {
311 double ener = cinp->
energy();
312 double time = cinp->
time() + SubEvtTimOffset;
317 std::unique_ptr<TileHit>& pHit = allHits[hit_idhash];
318 std::unique_ptr<TileHit> inValidHit(
nullptr);
319 std::unique_ptr<TileHit>& pHit_DigiHSTruth =
m_doDigiTruth ? allHits_DigiHSTruth[hit_idhash] : inValidHit;
325 pHit_DigiHSTruth->add(ener, time,
m_deltaT);
327 pHit_DigiHSTruth->add(0,time,
m_deltaT);
332 if (msgLvl(MSG::VERBOSE)) {
333 if (pHit->size() > 1 || pHit->energy() != 0.0)
334 msg(MSG::VERBOSE) <<
" nHit=" << nHit
335 <<
" id=" <<
m_tileID->to_string(hit_id, -1)
338 <<
" offs=" << SubEvtTimOffset
339 <<
" double hit" <<
endmsg;
341 msg(MSG::VERBOSE) <<
" nH=" << nHit
342 <<
" id=" <<
m_tileID->to_string(hit_id, -1)
343 <<
" HWid=" <<
m_tileID->to_string(pHit->pmt_HWID())
346 <<
" offs=" << SubEvtTimOffset
350 int hitsize = cinp->
size();
351 for (
int ind = 1; ind < hitsize; ++ind) {
353 time = cinp->
time(ind) + SubEvtTimOffset;
362 pHit_DigiHSTruth->add(ener, time,
m_deltaT);
364 pHit_DigiHSTruth->add(0, time,
m_deltaT);
368 if (msgLvl(MSG::VERBOSE))
369 msg(MSG::VERBOSE) <<
" nHit=" << nHit
370 <<
" id=" <<
m_tileID->to_string(hit_id, -1)
373 <<
" double hit from single hit" <<
endmsg;
392 for (; inpItr != end; ++inpItr) {
393 const TileHit * cinp = &(*inpItr);
394 eHitTot += cinp->
energy();
400 if (msgLvl(MSG::VERBOSE)) {
401 int hitsize = cinp->
size();
404 for (
int i = 0; i < hitsize; ++i) {
413 eHitTot += eHit - cinp->
energy();
415 msg(MSG::VERBOSE) <<
" nHit=" << nHit
419 <<
" Copy hit: ener=";
420 for (
int i = 0; i < hitsize; ++i)
421 msg(MSG::VERBOSE) << cinp->
energy(i) <<
" ";
422 msg(MSG::VERBOSE) <<
"time=";
423 for (
int i = 0; i < hitsize; ++i)
424 msg(MSG::VERBOSE) << cinp->
time(i) <<
" ";
433 for (; inpItr != end; ++inpItr) {
434 const TileHit * cinp = &(*inpItr);
435 int size = cinp->
size();
437 for (
int i = 0; i < size; ++i) {
449 if (msgLvl(MSG::VERBOSE)) {
450 int hitsize = cinp->
size();
451 msg(MSG::VERBOSE) <<
" nHit=" << nHit
455 <<
" Input hit: ener=";
456 for (
int i = 0; i < hitsize; ++i)
457 msg(MSG::VERBOSE) << cinp->
energy(i) <<
" ";
458 msg(MSG::VERBOSE) <<
"time=";
459 for (
int i = 0; i < hitsize; ++i)
460 msg(MSG::VERBOSE) << cinp->
time(i) <<
" ";
478 avtime = cosTriggerTime->time();
489 for (; inpItr != end; ++inpItr) {
490 const TileHit * cinp = &(*inpItr);
491 int size = cinp->
size();
492 for (
int i = 0; i < size; ++i) {
493 if (cinp->
time(i) < avtime) avtime = cinp->
time(i);
506 for (; inpItr != end; ++inpItr) {
507 const TileHit * cinp = &(*inpItr);
508 int size = cinp->
size();
509 for (
int i = 0; i < size; ++i) {
511 weight += cinp->
energy(i);
523 inpItr = inputHits->
begin();
526 for (; inpItr != end; ++inpItr) {
527 const TileHit * cinp = &(*inpItr);
530 int size = pHit->
size();
531 for (
int i = 0; i < size; ++i) {
533 eHitTot += cinp->
energy(i);
539 if (msgLvl(MSG::VERBOSE)) {
540 int hitsize = pHit->
size();
543 for (
int i = 0; i < hitsize; ++i) {
552 msg(MSG::VERBOSE) <<
" nHit=" << nHit
556 <<
" Output hit: ener=";
557 for (
int i = 0; i < hitsize; ++i)
558 msg(MSG::VERBOSE) << pHit->
energy(i) <<
" ";
559 msg(MSG::VERBOSE) <<
"time=";
560 for (
int i = 0; i < hitsize; ++i)
561 msg(MSG::VERBOSE) << pHit->
time(i) <<
" ";
581 ATH_MSG_DEBUG(
"Inside TileHitVecToCntTool processBunchXing" << bunchXing);
585 CLHEP::HepRandomEngine * engine = rngWrapper->
getEngine(Gaudi::Hive::currentContext());
590 while (iEvt != eSubEvents) {
595 std::vector<std::string>::const_iterator hitVecNamesItr =
m_hitVectorNames.begin();
596 std::vector<std::string>::const_iterator hitVecNamesEnd =
m_hitVectorNames.end();
597 for (; hitVecNamesItr != hitVecNamesEnd; ++hitVecNamesItr) {
599 const std::string hitVectorName(*hitVecNamesItr);
604 if (!(
m_mergeSvc->retrieveSingleSubEvtData(hitVectorName, inputHits, bunchXing, iEvt))){
605 ATH_MSG_ERROR(
" Tile Hit container not found for event key " << hitVectorName);
608 const double SubEvtTimOffset(iEvt->time());
611 if (fabs(SubEvtTimOffset) > 0.1) {
612 ATH_MSG_ERROR(
"Wrong time for in-time event: " << SubEvtTimOffset <<
" Ignoring all hits ");
614 ATH_MSG_DEBUG(
" New HitCont. TimeOffset=" << SubEvtTimOffset <<
", size =" << inputHits->
size());
619 bool isSignal =
false;
620 if(iEvt == bSubEvents) isSignal =
true;
628 if (!(
m_mergeSvc->retrieveSingleSubEvtData(hitVectorName, inputHits, bunchXing, iEvt))){
629 ATH_MSG_ERROR(
" Tile Hit container not found for event key " << hitVectorName);
642 ATH_MSG_DEBUG(
"Exiting processBunchXing in TileHitVecToCntTool");
644 return StatusCode::SUCCESS;
655 ATH_MSG_DEBUG(
"TileHitVecToCntTool processAllSubEvents started");
660 std::vector<std::unique_ptr<TileHit>> allHits;
661 auto hits = std::make_unique<TileHitNonConstContainer>(ownPolicy);
663 std::vector<std::unique_ptr<TileHit>> allHits_DigiHSTruth;
664 std::unique_ptr<TileHitNonConstContainer> hits_DigiHSTruth;
666 hits_DigiHSTruth = std::make_unique<TileHitNonConstContainer>(ownPolicy);
680 rngWrapper->
setSeed( name(), ctx );
681 CLHEP::HepRandomEngine * engine = rngWrapper->
getEngine(ctx);
685 for (
auto & inputHits : hitVectorHandles) {
686 if (!inputHits.isValid()) {
688 return StatusCode::FAILURE;
690 const double SubEvtTimeOffset(0.0);
692 ATH_MSG_DEBUG(
" New HitCont. TimeOffset=" << SubEvtTimeOffset <<
", size =" << inputHits->size());
697 return StatusCode::SUCCESS;
703 TimedHitContList hitContList;
705 if (!(
m_mergeSvc->retrieveSubEvtsData(hitVectorName, hitContList).isSuccess()) || hitContList.size() == 0) {
706 ATH_MSG_WARNING(
"Could not fill TimedHitContList for hit vector " << hitVectorName);
711 TimedHitContList::iterator iCont(hitContList.begin());
712 TimedHitContList::iterator iEndCont(hitContList.end());
715 if (iCont != iEndCont) {
717 const double SubEvtTimeOffset(iCont->first.time());
718 if (fabs(SubEvtTimeOffset) > 0.1) {
719 ATH_MSG_ERROR(
"Wrong time for in-time event: " << SubEvtTimeOffset <<
" Ignoring all hits ");
723 ATH_MSG_DEBUG(
" New HitCont. TimeOffset=" << SubEvtTimeOffset <<
", size =" << inputHits->
size());
730 for (; iCont != iEndCont; ++iCont) {
732 const double SubEvtTimeOffset(iCont->first.time());
735 ATH_MSG_VERBOSE(
" New HitCont. TimeOffset=" << SubEvtTimeOffset <<
", size =" << inputHits->
size());
736 bool isSignal =
false;
737 if(iCont == hitContList.begin() ) isSignal =
true;
748 ATH_MSG_WARNING(
"Hit Vector "<< hitVectorName <<
" not found in StoreGate");
763 return StatusCode::SUCCESS;
767 std::vector<std::unique_ptr<TileHit>>& allHits_DigiHSTruth,
768 std::unique_ptr<TileHitNonConstContainer>& hits,
769 std::unique_ptr<TileHitNonConstContainer>& hits_DigiHSTruth,
772 std::vector<std::unique_ptr<TileHit>>
::iterator iHit = allHits.
begin();
773 std::vector<std::unique_ptr<TileHit>>
::iterator lastHit = allHits.
end();
774 std::vector<std::unique_ptr<TileHit>>
::iterator iHit_DigiHSTruth = allHits_DigiHSTruth.
begin();
777 double eHitInTime = 0.0;
781 std::function<
TileHit*(std::unique_ptr<TileHit>&)> getOrRelease(&std::unique_ptr<TileHit>::get);
782 if (ownPolicy ==
SG::OWN_ELEMENTS) getOrRelease = &std::unique_ptr<TileHit>::release;
784 for (; iHit != lastHit; ++iHit) {
785 std::unique_ptr<TileHit>& hit = (*iHit);
786 if (hit->size() > 1 || hit->energy() != 0.0) {
787 eHitInTime += hit->energy();
788 hits->push_back(getOrRelease(hit));
789 if(
m_doDigiTruth) hits_DigiHSTruth->push_back(getOrRelease((*iHit_DigiHSTruth)));
795 ATH_MSG_DEBUG(
" nHitUni=" << nHitUni <<
" eHitInTime="<< eHitInTime);
799 std::unique_ptr<TileHitNonConstContainer>& hits,
800 std::unique_ptr<TileHitNonConstContainer>& hits_DigiHSTruth,
817 for (std::unique_ptr<TileHitCollection>& coll : *hits ) {
818 int frag_id = coll->identify();
828 for (; collIt != endcollIt; ++collIt) {
829 int frag_id = (*collIt)->identify();
842 CLHEP::HepRandomEngine * engine = rngWrapper->
getEngine(ctx);
850 collIt_DigiHSTruth = hits_DigiHSTruth->begin();
851 endColl_DigiHSTruth = hits_DigiHSTruth->end();
854 for (std::unique_ptr<TileHitCollection>& coll : *hits ) {
859 coll_DigiHSTruth = (*collIt_DigiHSTruth).
get();
860 hitItr_DigiHSTruth = coll_DigiHSTruth->
begin();
861 hitEnd_DigiHSTruth = coll_DigiHSTruth->
end();
871 int hitsize = pHit->size();
872 for (
int i = 0; i < hitsize; ++i) {
873 double thit = pHit->time(i);
880 if (
m_tileID->sample(pmt_id) == 3) {
885 double scaleFactor = 1.0;
888 pHit->scale(scaleFactor);
892 TileHit *pHit_DigiHSTruth = (*hitItr_DigiHSTruth);
893 pHit_DigiHSTruth->
scale(scaleFactor);
895 ++hitItr_DigiHSTruth;
904 auto hitCont = std::make_unique<TileHitContainer>(
false, ownPolicy);
906 for (std::unique_ptr<TileHitCollection>& coll : *hits ) {
907 CHECK(hitCont->addCollection (coll.release(), hashId++));
916 auto hitCont_DigiHSTruth = std::make_unique<TileHitContainer>(
false, ownPolicy);
917 size_t hashId_DigiHSTruth = 0;
918 for (std::unique_ptr<TileHitCollection>& coll : *hits_DigiHSTruth ) {
919 ATH_CHECK(hitCont_DigiHSTruth->addCollection (coll.release(), hashId_DigiHSTruth++));
923 ATH_CHECK( hitContainer_DigiHSTruth.
record(std::move(hitCont_DigiHSTruth)) );
927 return StatusCode::SUCCESS;
946 return StatusCode::SUCCESS;
958 / (Gaudi::Units::GeV / Gaudi::Units::MeV) * samplingFraction->
getSamplingFraction(drawerIdx, channel);
960 nPhotoElectrons = std::round(nPhotoElectrons * 1000) / 1000;
962 double pe = energy * nPhotoElectrons;
963 double pe_scale = 1., RndmPois = 1.;
968 RndmPois = std::max(0.0, RandGaussQ::shoot(engine, pe, sqrt(pe)));
969 pe_scale = RndmPois / pe;
973 double singleMEAN = 1.0;
974 double singleSIGMA = 1.0;
975 RndmPois = RandPoissonT::shoot(engine, pe);
979 for (
int i = 0; i < RndmPois; i++)
980 pe_scale += 1 / (1.08332) * std::max(0., RandGaussQ::shoot(engine, singleMEAN, singleSIGMA));
982 pe_scale /= RndmPois;
991 RndmPois = RandPoissonT::shoot(engine, pe);
992 pe_scale = RndmPois / pe;
999 RndmPois = std::max(0.0, RandGaussQ::shoot(engine, pe, sqrt(pe)));
1001 int nn = std::max(10, (
int) (pe * 10.0));
1002 double * ProbFunc =
new double[nn];
1003 ProbFunc[0] = exp(-pe);
1004 for (
int i = 1; i < nn; ++i) {
1005 ProbFunc[i] = ProbFunc[i - 1] * pe / i;
1007 RandGeneral* RandG =
new RandGeneral(ProbFunc, nn, 0);
1008 RndmPois = RandG->shoot(engine) * nn;
1014 pe_scale = RndmPois / pe;
1020 <<
" totEne=" << energy
1021 <<
", numPhElec=" << nPhotoElectrons
1023 <<
", rndmPoisson=" << RndmPois
1024 <<
", pe_scale=" << pe_scale);
1031 int module = frag_id & 0x3F;
1039 for (; hitIt != endHitIt; ++hitIt) {
1042 if (module ==
m_tileID->module(pmt_id)) {
1050 if (fromHitIt != coll->
end()) {
1052 <<
"] in module: " << module);
1053 bool isToHitNew =
false;
1055 int side =
m_tileID->side((*fromHitIt)->pmt_ID());
1057 toHit =
new TileHit(to_pmt_id);
1065 <<
" will be merged to " <<
m_tileID->to_string(toHit->
pmt_ID(), -1) );
1067 if (msgLvl(MSG::VERBOSE)) {
1068 msg(MSG::VERBOSE) <<
"Before merging (E1 cell) => " << (std::string) (**fromHitIt) <<
endmsg;
1069 msg(MSG::VERBOSE) <<
"Before merging (E1 cell) => " << (std::string) (*toHit) <<
endmsg;
1072 toHit->
add(*fromHitIt, 0.1);
1074 if (msgLvl(MSG::VERBOSE)) {
1075 msg(MSG::VERBOSE) <<
"After merging (E1 cell) => " << (std::string) (*toHit) <<
endmsg;
1076 msg(MSG::VERBOSE) <<
"TileHit to be deleted Id (E1 cell): " <<
m_tileID->to_string((*fromHitIt)->pmt_ID(), -1) <<
endmsg;
1079 coll->
erase(fromHitIt);
1089 int module = frag_id & 0x3F;
1097 for (; hitIt != endHitIt; ++hitIt) {
1108 if (fromHitIt != coll->
end()) {
1110 <<
"] in module: " << module);
1111 bool isToHitNew =
false;
1113 int side =
m_tileTBID->side((*fromHitIt)->pmt_ID());
1116 toHit =
new TileHit(to_pmt_id);
1126 if (msgLvl(MSG::VERBOSE)) {
1127 msg(MSG::VERBOSE) <<
"Before merging (MBTS) => " << (std::string) (**fromHitIt) <<
endmsg;
1128 msg(MSG::VERBOSE) <<
"Before merging (MBTS) => " << (std::string) (*toHit) <<
endmsg;
1131 toHit->
add(*fromHitIt, 0.1);
1133 if (msgLvl(MSG::VERBOSE)) {
1134 msg(MSG::VERBOSE) <<
"After merging (MBTS) => " << (std::string) (*toHit) <<
endmsg;
1135 msg(MSG::VERBOSE) <<
"TileHit to be deleted Id (MBTS): "
1139 coll->
erase(fromHitIt);
1148 for (std::unique_ptr<TileHitCollection>& coll : *hitCont) {
1150 int frag_id = coll->identify();
1151 int module = frag_id & 0x3F;
1153 std::vector<TileHit*> hits(48,
nullptr);
1154 std::vector<std::unique_ptr<TileHit>> otherModuleHits;
1156 [
this, &hits, &otherModuleHits, module, frag_hash] (
TileHit* hit) {
1157 Identifier pmt_id = hit->pmt_ID();
1158 int channel = m_tileHWID->channel(hit->pmt_HWID());
1159 TileHit* channelHit = hits[channel];
1161 mergeExtraHitToChannelHit(hit, channelHit);
1167 otherModuleHits.push_back(std::make_unique<TileHit>(*hit));
1170 hits[channel] = hit;
1175 for (std::unique_ptr<TileHit>& hit : otherModuleHits) {
1176 int channel =
m_tileHWID->channel(hit->pmt_HWID());
1177 TileHit* channelHit = hits[channel];
1181 hits[channel] = hit.get();
1182 coll->push_back(std::move(hit));
1191 <<
m_tileID->to_string(extraHit->
pmt_ID(), -1) <<
", will be merged to "
1196 channelHit->
add(extraHit, 0.1);
1206 allHits.reserve(
nHits);
1212 allHits.emplace_back(std::make_unique<TileHit>(hit_id, 0., 0.));
1213 allHits.back()->reserve(71);
1217 for (
int side = 0; side <
N_SIDE; ++side) {
1222 allHits[mbtsIndex] = std::make_unique<TileHit>(hit_id, 0., 0.);
1223 allHits[mbtsIndex]->reserve(71);
1232 allHits[e4prIndex] = std::make_unique<TileHit>(hit_id, 0., 0.);
1233 allHits[e4prIndex]->reserve(71);
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
Helpers for checking error return status codes and reporting errors.
#define CHECK(...)
Evaluate an expression and check for errors.
static const uint32_t nHits
Handle class for recording to StoreGate.
AtlasHitsVector< TileHit >::const_iterator TileHitVecConstIterator
AtlasHitsVector< TileHit > TileHitVector
A wrapper class for event-slot-local random engines.
void setSeed(const std::string &algName, const EventContext &ctx)
Set the random seed using a string (e.g.
CLHEP::HepRandomEngine * getEngine(const EventContext &ctx) const
Retrieve the random engine corresponding to the provided EventContext.
const_iterator begin() const
const_iterator end() const
const T * get(size_type n) const
Access an element, as an rvalue.
DataModel_detail::iterator< DataVector > iterator
Standard iterator.
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
iterator erase(iterator position)
Remove element at a given position.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
This class saves the "context" of an expanded identifier (ExpandedIdentifier) for compact or hash ver...
This is a "hash" representation of an Identifier.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
static unsigned int getDrawerIdx(unsigned int ros, unsigned int drawer)
Returns a drawer hash.
This is a minimal version of a TileHitContainer in which the saved collections remain non-const.
void setTime(float t, int ind=0)
Set time of ind-th sub-hit in a hit.
float time(int ind=0) const
Return time of ind-th sub-hit.
void scale(float coeff)
Scale energy of all sub-hits in a hit.
Identifier pmt_ID(void) const
Return logical ID of the pmt.
float energy(int ind=0) const
Return energy of ind-th sub-hit.
Identifier identify(void) const
Return logical ID of the pmt.
int add(float energy, float time)
Add sub-hit to a given hit.
int size(void) const
Return length of energy/time vectors.
std::vector< std::unique_ptr< TileHitCollection > >::iterator iterator
void push_back(element_t *rc)
Condition object to keep and provide Tile Calorimeter sampling fraction and number of photoelectrons.
float getNumberOfPhotoElectrons(unsigned int drawerIdx, unsigned int channel) const
Return number of photoelectrons per 1 GeV in Tile Calorimeter scintilator.
float getSamplingFraction(unsigned int drawerIdx, unsigned int channel) const
Return Tile Calorimeter sampling fraction.
@ OWN_ELEMENTS
this data object owns its elements
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
DataModel_detail::iterator< DVL > remove_if(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, Predicate pred)
Specialization of remove_if for DataVector/List.
std::list< value_t > type
type of the collection of timed data object