32 #include "CLHEP/Random/RandGaussZiggurat.h"
64 return StatusCode::FAILURE;
98 if (m_runVoltage < 2.3 || m_runVoltage > 3.2){
99 ATH_MSG_ERROR(
"STGC run voltage must be in kV and within fit domain of 2.3 kV to 3.2 kV");
100 return StatusCode::FAILURE;
111 return StatusCode::SUCCESS;
116 ATH_MSG_DEBUG(
"sTgcDigitizationTool::prepareEvent() called for " << nInputEvents <<
" input events" );
119 return StatusCode::SUCCESS;
126 ATH_MSG_DEBUG (
"sTgcDigitizationTool::in processBunchXing()" );
128 m_thpcsTGC = std::make_unique<TimedHitCollection<sTGCSimHit>>();
131 TimedHitCollList hitCollList;
134 bSubEvents, eSubEvents).isSuccess()) &&
135 hitCollList.empty()) {
137 return StatusCode::FAILURE;
139 ATH_MSG_VERBOSE(hitCollList.size() <<
" sTGCSimHitCollection with key " <<
147 for( ; iColl != endColl; ++iColl){
149 auto hitCollPtr = std::make_unique<sTGCSimHitCollection>(*iColl->second);
152 ATH_MSG_DEBUG(
"sTGCSimHitCollection found with " << hitCollPtr->size() <<
" hits");
154 <<
" index: " << timeIndex.
index()
155 <<
" type: " << timeIndex.
type());
157 m_thpcsTGC->insert(timeIndex, hitCollPtr.get());
160 return StatusCode::SUCCESS;
173 if (!hitCollection.
isValid()) {
174 ATH_MSG_ERROR(
"Could not get sTGCSimHitCollection container " << hitCollection.
name() <<
" from store " << hitCollection.
store());
175 return StatusCode::FAILURE;
179 m_thpcsTGC = std::make_unique<TimedHitCollection<sTGCSimHit>>(1);
181 ATH_MSG_DEBUG(
"sTGCSimHitCollection found with " << hitCollection->
size() <<
" hits");
182 return StatusCode::SUCCESS;
186 TimedHitCollList hitCollList;
190 return StatusCode::FAILURE;
192 if (hitCollList.empty()) {
194 return StatusCode::FAILURE;
202 m_thpcsTGC = std::make_unique<TimedHitCollection<sTGCSimHit>>();
205 return StatusCode::FAILURE;
211 while (iColl != endColl) {
213 m_thpcsTGC->insert(iColl->first, p_collection);
214 ATH_MSG_DEBUG (
"sTGC SimHitCollection found with " << p_collection->
size() <<
" hits" );
218 return StatusCode::SUCCESS;
229 return StatusCode::SUCCESS;
237 ATH_MSG_DEBUG (
" sTgcDigitizationTool::processAllSubEvents()" );
246 return StatusCode::SUCCESS;
251 const CondType* & condPtr)
const{
253 ATH_MSG_DEBUG(
"No key has been configured for object "<<
typeid(CondType).
name()<<
". Clear pointer");
255 return StatusCode::SUCCESS;
258 if (!readHandle.isValid()){
260 return StatusCode::FAILURE;
262 condPtr = readHandle.cptr();
263 return StatusCode::SUCCESS;
281 ATH_CHECK(digitContainer.
record(std::make_unique<sTgcDigitContainer>(idHelper.module_hash_max())));
282 ATH_MSG_DEBUG (
"sTgcDigitContainer recorded in StoreGate." );
286 ATH_CHECK(sdoContainer.
record(std::make_unique<MuonSimDataCollection>()));
293 sTgcSimDigitCont unmergedPadDigits{}, unmergedStripDigits{}, unmergedWireDigits{};
296 ATH_MSG_DEBUG(
"create Digit container of size " << idHelper.module_hash_max());
298 double earliestEventTime = 9999;
305 ATH_MSG_VERBOSE(
"Looping over hit " << nhits+1 <<
" on this Detector Element." );
312 if(eventTime < earliestEventTime) earliestEventTime = eventTime;
324 if (hit_kineticEnergy > 0.) {
327 ATH_MSG_DEBUG(
"Skip electron hit with kinetic energy " << hit_kineticEnergy
337 ATH_MSG_VERBOSE(
"Skip hit with a direction perpendicular to the beam line, ie z-component is less than 0.00001 mm.");
343 ATH_MSG_DEBUG(
"Updated hit global time to include off set of " << eventTime <<
" ns from OOT bunch.");
349 const int idHit = hit.
sTGCId();
357 bool acceptHit =
true;
381 int surfHash_wire = detEL->
surfaceHash(idHelper.gasGap(layid),
382 sTgcIdHelper::sTgcChannelTypes::Wire);
394 const double scale = Amg::intersect<3>(LPOS, LOCDIRE, Amg::Vector3D::UnitZ(), 0.).value_or(0);
404 ATH_MSG_DEBUG(
"sTgcDigitizationTool::doDigitization hits mapped");
417 double globalHitTime = temp_hit.
globalTime() + eventTime;
419 double bunchTime = globalHitTime - tof;
423 if (digiHits.empty()) {
427 for( std::unique_ptr<sTgcDigit>&
digit : digiHits) {
437 double newTime =
digit->time();
438 int newChannelType = idHelper.channelType(newDigitId);
442 if(newChannelType== sTgcIdHelper::sTgcChannelTypes::Strip)
443 newTime += timeJitterElectronicsStrip;
445 newTime += timeJitterElectronicsPad;
449 newTime += bunchTime;
451 newTime += globalHitTime;
453 double newCharge =
digit->charge();
455 bool isDead{
false},
isPileup{eventId != 0};
456 ATH_MSG_VERBOSE(
"Hit is from the main signal subevent if eventId is zero, eventId = " << eventId <<
" newTime: " << newTime);
462 <<
" BC tag = " << newDigit.
bcTag()
463 <<
" digitTime = " << newDigit.
time()
464 <<
" charge = " << newDigit.
charge()) ;
469 std::vector<MuonSimData::Deposit> deposits;
470 deposits.push_back(std::move(deposit));
475 simData.setPosition(glob_hitOnSurf_wire);
476 simData.setTime(globalHitTime);
477 const unsigned int modHash =
static_cast<unsigned>(
m_idHelperSvc->detElementHash(newDigitId));
478 sTgcSimDigitCont& contToPush = newChannelType == sTgcIdHelper::sTgcChannelTypes::Pad ? unmergedPadDigits :
479 newChannelType == sTgcIdHelper::sTgcChannelTypes::Strip ? unmergedStripDigits : unmergedWireDigits;
481 if (contToPush.size() <= modHash) contToPush.resize(modHash + 1);
482 contToPush[modHash].emplace_back(std::move(
simData), std::move(newDigit));
513 false, outputDigits, *sdoContainer));
518 false, outputDigits, *sdoContainer));
523 if (digits.empty())
continue;
525 const IdentifierHash modHash =
m_idHelperSvc->moduleHash(elemID);
526 std::unique_ptr<sTgcDigitCollection> collection = std::make_unique<sTgcDigitCollection>(elemID, modHash);
527 collection->
insert(collection->
end(), std::make_move_iterator(digits.begin()),
528 std::make_move_iterator(digits.end()));
531 return StatusCode::SUCCESS;
540 if(digitTime > 0) bunchInteger = (
int)(abs(digitTime/25.0));
541 else bunchInteger = (
int)(abs(digitTime/25.0)) + 1;
542 bctag = (bctag | bunchInteger);
543 if(digitTime < 0) bctag = ~bctag;
555 ATH_MSG_ERROR(
"Cannot find retrieve VMM threshold from conditions data base!");
557 ATH_MSG_ERROR(
"Cannot convert VMM charge threshold via conditions data!");
567 rngWrapper->
setSeed( rngName, ctx );
568 CLHEP::HepRandomEngine* engine = rngWrapper->
getEngine(ctx);
576 const double vmmDeadTime,
577 const bool isNeighbourOn,
585 if (digitsInCham.empty())
continue;
588 digitsInCham, isNeighbourOn);
590 if (mergedDigits.empty())
continue;
592 const IdentifierHash
hash =
m_idHelperSvc->moduleHash(mergedDigits.front().identify());
593 const unsigned int hashIdx =
static_cast<unsigned>(
hash);
595 if (
hash >= outDigitContainer.size()) {
596 outDigitContainer.resize(
hash + 1);
600 outSdoContainer.insert(std::make_pair(merged.identify(), std::move(merged.getSimData())));
602 bool acceptDigit{
true};
603 float chargeAfterSmearing = merged.getDigit().charge();
613 if (idHelper.channelType(merged.identify()) == sTgcIdHelper::sTgcChannelTypes::Strip &&
614 chargeAfterSmearing < 0.001) {
617 std::unique_ptr<sTgcDigit> finalDigit = std::make_unique<sTgcDigit>(std::move(merged.getDigit()));
622 " BC tag = " << finalDigit->
bcTag()<<
623 " digitTime = " << finalDigit->
time() <<
624 " charge = " << finalDigit->
charge());
625 outDigitContainer[hashIdx].push_back(std::move(finalDigit));
628 return StatusCode::SUCCESS;
632 const double vmmDeadTime,
634 const bool isNeighborOn)
const {
639 std::stable_sort(unmergedDigits.begin(), unmergedDigits.end(),
641 const int layA = idHelper.gasGap(a.identify());
642 const int layB = idHelper.gasGap(b.identify());
643 if (layA != layB) return layA < layB;
644 const int chA = idHelper.channel(a.identify());
645 const int chB = idHelper.channel(b.identify());
646 if (chA != chB) return chA < chB;
647 return a.time() < b.time();
651 premerged.reserve(unmergedDigits.size());
652 savedDigits.reserve(premerged.capacity());
656 if (!isNeighborOn || savedDigits.empty())
return false;
657 if (savedDigits.back().identify() == candidate.identify() &&
658 std::abs(savedDigits.back().time() - candidate.time()) < vmmDeadTime) {
662 const Identifier digitId = candidate.identify();
663 const int channel = idHelper.channel(digitId);
664 const int maxChannel = detMgr->getsTgcReadoutElement(digitId)->numberOfStrips(digitId);
667 if (neighbour ==
channel)
continue;
668 const Identifier neighbourId = idHelper.channelID(digitId,
669 idHelper.multilayer(digitId),
670 idHelper.gasGap(digitId),
671 idHelper.channelType(digitId), neighbour);
675 return known.identify() == neighbourId &&
676 known.getDigit().charge() > threshold &&
677 std::abs(known.time() - candidate.time()) < m_hitTimeMergeThreshold;
678 }) != savedDigits.end())
return true;
692 sTgcDigit& digit1{(*merge_me).getDigit()};
693 double totalCharge = digit1.
charge();
694 double weightedTime = digit1.time();
697 for ( ; merge_with!= unmergedDigits.end(); ++merge_with) {
699 if ((*merge_with).identify() != (*merge_me).identify()) {
702 const sTgcDigit& mergeDigit{(*merge_with).getDigit()};
708 weightedTime = (weightedTime * totalCharge + mergeDigit.time() * mergeDigit.charge())
709 / (totalCharge + mergeDigit.charge());
711 totalCharge += mergeDigit.
charge();
713 digit1.set_charge(totalCharge);
714 digit1.set_time(weightedTime);
716 if (!savedDigits.empty() &&
717 savedDigits.back().identify() == digit1.identify() &&
718 std::abs(savedDigits.back().time() - digit1.time()) <= vmmDeadTime)
continue;
719 if (digit1.charge() >
threshold || passNeigbourLogic(mergedHit)){
720 savedDigits.emplace_back(std::move(mergedHit));
721 }
else if (isNeighborOn) {
722 premerged.emplace_back(std::move(mergedHit));
725 std::copy_if(std::make_move_iterator(premerged.begin()),
726 std::make_move_iterator(premerged.end()),
727 std::back_inserter(savedDigits), passNeigbourLogic);