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 {
288 for (; inpItr != end; ++inpItr) {
290 const TileHit * cinp = &(*inpItr);
294 int side = std::max(0,
m_tileTBID->type(hit_id));
302 m_tileID->get_hash(hit_id, hit_idhash, &pmt_context);
305 if (hit_idhash >= allHits.size()) {
310 double ener = cinp->
energy();
311 double time = cinp->
time() + SubEvtTimOffset;
316 std::unique_ptr<TileHit>& pHit = allHits[hit_idhash];
317 std::unique_ptr<TileHit> inValidHit(
nullptr);
318 std::unique_ptr<TileHit>& pHit_DigiHSTruth =
m_doDigiTruth ? allHits_DigiHSTruth[hit_idhash] : inValidHit;
324 pHit_DigiHSTruth->add(ener, time,
m_deltaT);
326 pHit_DigiHSTruth->add(0,time,
m_deltaT);
331 if (msgLvl(MSG::VERBOSE)) {
332 if (pHit->size() > 1 || pHit->energy() != 0.0)
333 msg(MSG::VERBOSE) <<
" nHit=" << nHit
334 <<
" id=" <<
m_tileID->to_string(hit_id, -1)
337 <<
" offs=" << SubEvtTimOffset
338 <<
" double hit" <<
endmsg;
340 msg(MSG::VERBOSE) <<
" nH=" << nHit
341 <<
" id=" <<
m_tileID->to_string(hit_id, -1)
342 <<
" HWid=" <<
m_tileID->to_string(pHit->pmt_HWID())
345 <<
" offs=" << SubEvtTimOffset
349 int hitsize = cinp->
size();
350 for (
int ind = 1; ind < hitsize; ++ind) {
352 time = cinp->
time(ind) + SubEvtTimOffset;
361 pHit_DigiHSTruth->add(ener, time,
m_deltaT);
363 pHit_DigiHSTruth->add(0, time,
m_deltaT);
367 if (msgLvl(MSG::VERBOSE))
368 msg(MSG::VERBOSE) <<
" nHit=" << nHit
369 <<
" id=" <<
m_tileID->to_string(hit_id, -1)
372 <<
" double hit from single hit" <<
endmsg;
391 for (; inpItr != end; ++inpItr) {
392 const TileHit * cinp = &(*inpItr);
393 eHitTot += cinp->
energy();
399 if (msgLvl(MSG::VERBOSE)) {
400 int hitsize = cinp->
size();
403 for (
int i = 0; i < hitsize; ++i) {
412 eHitTot += eHit - cinp->
energy();
414 msg(MSG::VERBOSE) <<
" nHit=" << nHit
418 <<
" Copy hit: ener=";
419 for (
int i = 0; i < hitsize; ++i)
420 msg(MSG::VERBOSE) << cinp->
energy(i) <<
" ";
421 msg(MSG::VERBOSE) <<
"time=";
422 for (
int i = 0; i < hitsize; ++i)
423 msg(MSG::VERBOSE) << cinp->
time(i) <<
" ";
432 for (; inpItr != end; ++inpItr) {
433 const TileHit * cinp = &(*inpItr);
436 for (
int i = 0; i <
size; ++i) {
448 if (msgLvl(MSG::VERBOSE)) {
449 int hitsize = cinp->
size();
450 msg(MSG::VERBOSE) <<
" nHit=" << nHit
454 <<
" Input hit: ener=";
455 for (
int i = 0; i < hitsize; ++i)
456 msg(MSG::VERBOSE) << cinp->
energy(i) <<
" ";
457 msg(MSG::VERBOSE) <<
"time=";
458 for (
int i = 0; i < hitsize; ++i)
459 msg(MSG::VERBOSE) << cinp->
time(i) <<
" ";
477 avtime = cosTriggerTime->time();
488 for (; inpItr != end; ++inpItr) {
489 const TileHit * cinp = &(*inpItr);
491 for (
int i = 0; i <
size; ++i) {
492 if (cinp->
time(i) < avtime) avtime = cinp->
time(i);
505 for (; inpItr != end; ++inpItr) {
506 const TileHit * cinp = &(*inpItr);
508 for (
int i = 0; i <
size; ++i) {
510 weight += cinp->
energy(i);
522 inpItr = inputHits->
begin();
525 for (; inpItr != end; ++inpItr) {
526 const TileHit * cinp = &(*inpItr);
530 for (
int i = 0; i <
size; ++i) {
532 eHitTot += cinp->
energy(i);
538 if (msgLvl(MSG::VERBOSE)) {
539 int hitsize = pHit->
size();
542 for (
int i = 0; i < hitsize; ++i) {
551 msg(MSG::VERBOSE) <<
" nHit=" << nHit
555 <<
" Output hit: ener=";
556 for (
int i = 0; i < hitsize; ++i)
557 msg(MSG::VERBOSE) << pHit->
energy(i) <<
" ";
558 msg(MSG::VERBOSE) <<
"time=";
559 for (
int i = 0; i < hitsize; ++i)
560 msg(MSG::VERBOSE) << pHit->
time(i) <<
" ";
580 ATH_MSG_DEBUG(
"Inside TileHitVecToCntTool processBunchXing" << bunchXing);
584 CLHEP::HepRandomEngine * engine = rngWrapper->
getEngine(Gaudi::Hive::currentContext());
589 while (iEvt != eSubEvents) {
594 std::vector<std::string>::const_iterator hitVecNamesItr =
m_hitVectorNames.begin();
595 std::vector<std::string>::const_iterator hitVecNamesEnd =
m_hitVectorNames.end();
596 for (; hitVecNamesItr != hitVecNamesEnd; ++hitVecNamesItr) {
598 const std::string hitVectorName(*hitVecNamesItr);
603 if (!(
m_mergeSvc->retrieveSingleSubEvtData(hitVectorName, inputHits, bunchXing, iEvt))){
604 ATH_MSG_ERROR(
" Tile Hit container not found for event key " << hitVectorName);
607 const double SubEvtTimOffset(iEvt->time());
610 if (fabs(SubEvtTimOffset) > 0.1) {
611 ATH_MSG_ERROR(
"Wrong time for in-time event: " << SubEvtTimOffset <<
" Ignoring all hits ");
613 ATH_MSG_DEBUG(
" New HitCont. TimeOffset=" << SubEvtTimOffset <<
", size =" << inputHits->
size());
618 bool isSignal =
false;
619 if(iEvt == bSubEvents) isSignal =
true;
627 if (!(
m_mergeSvc->retrieveSingleSubEvtData(hitVectorName, inputHits, bunchXing, iEvt))){
628 ATH_MSG_ERROR(
" Tile Hit container not found for event key " << hitVectorName);
641 ATH_MSG_DEBUG(
"Exiting processBunchXing in TileHitVecToCntTool");
643 return StatusCode::SUCCESS;
654 ATH_MSG_DEBUG(
"TileHitVecToCntTool processAllSubEvents started");
659 std::vector<std::unique_ptr<TileHit>> allHits;
660 auto hits = std::make_unique<TileHitNonConstContainer>(ownPolicy);
662 std::vector<std::unique_ptr<TileHit>> allHits_DigiHSTruth;
663 std::unique_ptr<TileHitNonConstContainer> hits_DigiHSTruth;
665 hits_DigiHSTruth = std::make_unique<TileHitNonConstContainer>(ownPolicy);
679 rngWrapper->
setSeed( name(), ctx );
680 CLHEP::HepRandomEngine * engine = rngWrapper->
getEngine(ctx);
684 for (
auto & inputHits : hitVectorHandles) {
685 if (!inputHits.isValid()) {
687 return StatusCode::FAILURE;
689 const double SubEvtTimeOffset(0.0);
691 ATH_MSG_DEBUG(
" New HitCont. TimeOffset=" << SubEvtTimeOffset <<
", size =" << inputHits->size());
696 return StatusCode::SUCCESS;
702 TimedHitContList hitContList;
704 if (!(
m_mergeSvc->retrieveSubEvtsData(hitVectorName, hitContList).isSuccess()) || hitContList.size() == 0) {
705 ATH_MSG_WARNING(
"Could not fill TimedHitContList for hit vector " << hitVectorName);
710 TimedHitContList::iterator iCont(hitContList.begin());
711 TimedHitContList::iterator iEndCont(hitContList.end());
714 if (iCont != iEndCont) {
716 const double SubEvtTimeOffset(iCont->first.time());
717 if (fabs(SubEvtTimeOffset) > 0.1) {
718 ATH_MSG_ERROR(
"Wrong time for in-time event: " << SubEvtTimeOffset <<
" Ignoring all hits ");
722 ATH_MSG_DEBUG(
" New HitCont. TimeOffset=" << SubEvtTimeOffset <<
", size =" << inputHits->
size());
729 for (; iCont != iEndCont; ++iCont) {
731 const double SubEvtTimeOffset(iCont->first.time());
734 ATH_MSG_VERBOSE(
" New HitCont. TimeOffset=" << SubEvtTimeOffset <<
", size =" << inputHits->
size());
735 bool isSignal =
false;
736 if(iCont == hitContList.begin() ) isSignal =
true;
747 ATH_MSG_WARNING(
"Hit Vector "<< hitVectorName <<
" not found in StoreGate");
762 return StatusCode::SUCCESS;
766 std::vector<std::unique_ptr<TileHit>>& allHits_DigiHSTruth,
767 std::unique_ptr<TileHitNonConstContainer>& hits,
768 std::unique_ptr<TileHitNonConstContainer>& hits_DigiHSTruth,
771 std::vector<std::unique_ptr<TileHit>>
::iterator iHit = allHits.
begin();
772 std::vector<std::unique_ptr<TileHit>>
::iterator lastHit = allHits.
end();
773 std::vector<std::unique_ptr<TileHit>>
::iterator iHit_DigiHSTruth = allHits_DigiHSTruth.
begin();
776 double eHitInTime = 0.0;
780 std::function<
TileHit*(std::unique_ptr<TileHit>&)> getOrRelease(&std::unique_ptr<TileHit>::get);
781 if (ownPolicy ==
SG::OWN_ELEMENTS) getOrRelease = &std::unique_ptr<TileHit>::release;
783 for (; iHit != lastHit; ++iHit) {
784 std::unique_ptr<TileHit>& hit = (*iHit);
785 if (hit->size() > 1 || hit->energy() != 0.0) {
786 eHitInTime += hit->energy();
787 hits->push_back(getOrRelease(hit));
788 if(
m_doDigiTruth) hits_DigiHSTruth->push_back(getOrRelease((*iHit_DigiHSTruth)));
794 ATH_MSG_DEBUG(
" nHitUni=" << nHitUni <<
" eHitInTime="<< eHitInTime);
798 std::unique_ptr<TileHitNonConstContainer>& hits,
799 std::unique_ptr<TileHitNonConstContainer>& hits_DigiHSTruth,
816 for (std::unique_ptr<TileHitCollection>& coll : *hits ) {
817 int frag_id = coll->identify();
827 for (; collIt != endcollIt; ++collIt) {
828 int frag_id = (*collIt)->identify();
841 CLHEP::HepRandomEngine * engine = rngWrapper->
getEngine(ctx);
849 collIt_DigiHSTruth = hits_DigiHSTruth->begin();
850 endColl_DigiHSTruth = hits_DigiHSTruth->end();
853 for (std::unique_ptr<TileHitCollection>& coll : *hits ) {
858 coll_DigiHSTruth = (*collIt_DigiHSTruth).
get();
859 hitItr_DigiHSTruth = coll_DigiHSTruth->
begin();
860 hitEnd_DigiHSTruth = coll_DigiHSTruth->
end();
870 int hitsize = pHit->size();
871 for (
int i = 0; i < hitsize; ++i) {
872 double thit = pHit->time(i);
879 if (
m_tileID->sample(pmt_id) == 3) {
884 double scaleFactor = 1.0;
887 pHit->scale(scaleFactor);
891 TileHit *pHit_DigiHSTruth = (*hitItr_DigiHSTruth);
892 pHit_DigiHSTruth->
scale(scaleFactor);
894 ++hitItr_DigiHSTruth;
903 auto hitCont = std::make_unique<TileHitContainer>(
false, ownPolicy);
905 for (std::unique_ptr<TileHitCollection>& coll : *hits ) {
906 CHECK(hitCont->addCollection (coll.release(), hashId++));
915 auto hitCont_DigiHSTruth = std::make_unique<TileHitContainer>(
false, ownPolicy);
916 size_t hashId_DigiHSTruth = 0;
917 for (std::unique_ptr<TileHitCollection>& coll : *hits_DigiHSTruth ) {
918 ATH_CHECK(hitCont_DigiHSTruth->addCollection (coll.release(), hashId_DigiHSTruth++));
922 ATH_CHECK( hitContainer_DigiHSTruth.
record(std::move(hitCont_DigiHSTruth)) );
926 return StatusCode::SUCCESS;
945 return StatusCode::SUCCESS;
957 / (Gaudi::Units::GeV / Gaudi::Units::MeV) * samplingFraction->
getSamplingFraction(drawerIdx, channel);
959 nPhotoElectrons = std::round(nPhotoElectrons * 1000) / 1000;
961 double pe = energy * nPhotoElectrons;
962 double pe_scale = 1., RndmPois = 1.;
967 RndmPois = std::max(0.0, RandGaussQ::shoot(engine, pe, sqrt(pe)));
968 pe_scale = RndmPois / pe;
972 double singleMEAN = 1.0;
973 double singleSIGMA = 1.0;
974 RndmPois = RandPoissonT::shoot(engine, pe);
978 for (
int i = 0; i < RndmPois; i++)
979 pe_scale += 1 / (1.08332) * std::max(0., RandGaussQ::shoot(engine, singleMEAN, singleSIGMA));
981 pe_scale /= RndmPois;
990 RndmPois = RandPoissonT::shoot(engine, pe);
991 pe_scale = RndmPois / pe;
998 RndmPois = std::max(0.0, RandGaussQ::shoot(engine, pe, sqrt(pe)));
1000 int nn = std::max(10, (
int) (pe * 10.0));
1001 double * ProbFunc =
new double[nn];
1002 ProbFunc[0] = exp(-pe);
1003 for (
int i = 1; i < nn; ++i) {
1004 ProbFunc[i] = ProbFunc[i - 1] * pe / i;
1006 RandGeneral* RandG =
new RandGeneral(ProbFunc, nn, 0);
1007 RndmPois = RandG->shoot(engine) * nn;
1013 pe_scale = RndmPois / pe;
1019 <<
" totEne=" << energy
1020 <<
", numPhElec=" << nPhotoElectrons
1022 <<
", rndmPoisson=" << RndmPois
1023 <<
", pe_scale=" << pe_scale);
1030 int module = frag_id & 0x3F;
1038 for (; hitIt != endHitIt; ++hitIt) {
1041 if (module ==
m_tileID->module(pmt_id)) {
1049 if (fromHitIt != coll->
end()) {
1051 <<
"] in module: " << module);
1052 bool isToHitNew =
false;
1054 int side =
m_tileID->side((*fromHitIt)->pmt_ID());
1056 toHit =
new TileHit(to_pmt_id);
1064 <<
" will be merged to " <<
m_tileID->to_string(toHit->
pmt_ID(), -1) );
1066 if (msgLvl(MSG::VERBOSE)) {
1067 msg(MSG::VERBOSE) <<
"Before merging (E1 cell) => " << (std::string) (**fromHitIt) <<
endmsg;
1068 msg(MSG::VERBOSE) <<
"Before merging (E1 cell) => " << (std::string) (*toHit) <<
endmsg;
1071 toHit->
add(*fromHitIt, 0.1);
1073 if (msgLvl(MSG::VERBOSE)) {
1074 msg(MSG::VERBOSE) <<
"After merging (E1 cell) => " << (std::string) (*toHit) <<
endmsg;
1075 msg(MSG::VERBOSE) <<
"TileHit to be deleted Id (E1 cell): " <<
m_tileID->to_string((*fromHitIt)->pmt_ID(), -1) <<
endmsg;
1078 coll->
erase(fromHitIt);
1088 int module = frag_id & 0x3F;
1096 for (; hitIt != endHitIt; ++hitIt) {
1107 if (fromHitIt != coll->
end()) {
1109 <<
"] in module: " << module);
1110 bool isToHitNew =
false;
1112 int side =
m_tileTBID->side((*fromHitIt)->pmt_ID());
1115 toHit =
new TileHit(to_pmt_id);
1125 if (msgLvl(MSG::VERBOSE)) {
1126 msg(MSG::VERBOSE) <<
"Before merging (MBTS) => " << (std::string) (**fromHitIt) <<
endmsg;
1127 msg(MSG::VERBOSE) <<
"Before merging (MBTS) => " << (std::string) (*toHit) <<
endmsg;
1130 toHit->
add(*fromHitIt, 0.1);
1132 if (msgLvl(MSG::VERBOSE)) {
1133 msg(MSG::VERBOSE) <<
"After merging (MBTS) => " << (std::string) (*toHit) <<
endmsg;
1134 msg(MSG::VERBOSE) <<
"TileHit to be deleted Id (MBTS): "
1138 coll->
erase(fromHitIt);
1147 for (std::unique_ptr<TileHitCollection>& coll : *hitCont) {
1149 int frag_id = coll->identify();
1150 int module = frag_id & 0x3F;
1152 std::vector<TileHit*> hits(48,
nullptr);
1153 std::vector<std::unique_ptr<TileHit>> otherModuleHits;
1155 [
this, &hits, &otherModuleHits, module, frag_hash] (
TileHit* hit) {
1156 Identifier pmt_id = hit->pmt_ID();
1157 int channel = m_tileHWID->channel(hit->pmt_HWID());
1158 TileHit* channelHit = hits[channel];
1160 mergeExtraHitToChannelHit(hit, channelHit);
1166 otherModuleHits.push_back(std::make_unique<TileHit>(*hit));
1169 hits[channel] = hit;
1174 for (std::unique_ptr<TileHit>& hit : otherModuleHits) {
1175 int channel =
m_tileHWID->channel(hit->pmt_HWID());
1176 TileHit* channelHit = hits[channel];
1180 hits[channel] = hit.get();
1181 coll->push_back(std::move(hit));
1190 <<
m_tileID->to_string(extraHit->
pmt_ID(), -1) <<
", will be merged to "
1195 channelHit->
add(extraHit, 0.1);
1205 allHits.reserve(
nHits);
1211 allHits.emplace_back(std::make_unique<TileHit>(hit_id, 0., 0.));
1212 allHits.back()->reserve(71);
1216 for (
int side = 0; side <
N_SIDE; ++side) {
1221 allHits[mbtsIndex] = std::make_unique<TileHit>(hit_id, 0., 0.);
1222 allHits[mbtsIndex]->reserve(71);
1231 allHits[e4prIndex] = std::make_unique<TileHit>(hit_id, 0., 0.);
1232 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.
size_t size() const
Number of registered mappings.
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