32 #include "CLHEP/Random/RandGaussZiggurat.h"
74 return StatusCode::FAILURE;
108 if (m_runVoltage < 2.3 || m_runVoltage > 3.2){
109 ATH_MSG_ERROR(
"STGC run voltage must be in kV and within fit domain of 2.3 kV to 3.2 kV");
110 return StatusCode::FAILURE;
121 return StatusCode::SUCCESS;
126 ATH_MSG_DEBUG(
"sTgcDigitizationTool::prepareEvent() called for " << nInputEvents <<
" input events" );
129 return StatusCode::SUCCESS;
136 ATH_MSG_DEBUG (
"sTgcDigitizationTool::in processBunchXing()" );
138 m_thpcsTGC = std::make_unique<TimedHitCollection<sTGCSimHit>>();
141 TimedHitCollList hitCollList;
144 bSubEvents, eSubEvents).isSuccess()) &&
145 hitCollList.empty()) {
147 return StatusCode::FAILURE;
149 ATH_MSG_VERBOSE(hitCollList.size() <<
" sTGCSimHitCollection with key " <<
157 for( ; iColl != endColl; ++iColl){
159 auto hitCollPtr = std::make_unique<sTGCSimHitCollection>(*iColl->second);
162 ATH_MSG_DEBUG(
"sTGCSimHitCollection found with " << hitCollPtr->size() <<
" hits");
164 <<
" index: " << timeIndex.
index()
165 <<
" type: " << timeIndex.
type());
167 m_thpcsTGC->insert(timeIndex, hitCollPtr.get());
170 return StatusCode::SUCCESS;
183 if (!hitCollection.
isValid()) {
184 ATH_MSG_ERROR(
"Could not get sTGCSimHitCollection container " << hitCollection.
name() <<
" from store " << hitCollection.
store());
185 return StatusCode::FAILURE;
189 m_thpcsTGC = std::make_unique<TimedHitCollection<sTGCSimHit>>(1);
191 ATH_MSG_DEBUG(
"sTGCSimHitCollection found with " << hitCollection->
size() <<
" hits");
192 return StatusCode::SUCCESS;
196 TimedHitCollList hitCollList;
200 return StatusCode::FAILURE;
202 if (hitCollList.empty()) {
204 return StatusCode::FAILURE;
212 m_thpcsTGC = std::make_unique<TimedHitCollection<sTGCSimHit>>();
215 return StatusCode::FAILURE;
221 while (iColl != endColl) {
223 m_thpcsTGC->insert(iColl->first, p_collection);
224 ATH_MSG_DEBUG (
"sTGC SimHitCollection found with " << p_collection->
size() <<
" hits" );
228 return StatusCode::SUCCESS;
239 return StatusCode::SUCCESS;
247 ATH_MSG_DEBUG (
" sTgcDigitizationTool::processAllSubEvents()" );
256 return StatusCode::SUCCESS;
261 const CondType* & condPtr)
const{
263 ATH_MSG_DEBUG(
"No key has been configured for object "<<
typeid(CondType).
name()<<
". Clear pointer");
265 return StatusCode::SUCCESS;
268 if (!readHandle.isValid()){
270 return StatusCode::FAILURE;
272 condPtr = readHandle.cptr();
273 return StatusCode::SUCCESS;
291 ATH_CHECK(digitContainer.
record(std::make_unique<sTgcDigitContainer>(idHelper.module_hash_max())));
292 ATH_MSG_DEBUG (
"sTgcDigitContainer recorded in StoreGate." );
296 ATH_CHECK(sdoContainer.
record(std::make_unique<MuonSimDataCollection>()));
303 sTgcSimDigitCont unmergedPadDigits{}, unmergedStripDigits{}, unmergedWireDigits{};
306 ATH_MSG_DEBUG(
"create Digit container of size " << idHelper.module_hash_max());
308 double earliestEventTime = 9999;
315 ATH_MSG_VERBOSE(
"Looping over hit " << nhits+1 <<
" on this Detector Element." );
322 if(eventTime < earliestEventTime) earliestEventTime = eventTime;
334 if (hit_kineticEnergy > 0.) {
337 ATH_MSG_DEBUG(
"Skip electron hit with kinetic energy " << hit_kineticEnergy
347 ATH_MSG_VERBOSE(
"Skip hit with a direction perpendicular to the beam line, ie z-component is less than 0.00001 mm.");
353 ATH_MSG_DEBUG(
"Updated hit global time to include off set of " << eventTime <<
" ns from OOT bunch.");
359 const int idHit = hit.
sTGCId();
367 bool acceptHit =
true;
391 int surfHash_wire = detEL->
surfaceHash(idHelper.gasGap(layid),
392 sTgcIdHelper::sTgcChannelTypes::Wire);
404 const double scale = Amg::intersect<3>(LPOS, LOCDIRE, Amg::Vector3D::UnitZ(), 0.).value_or(0);
414 ATH_MSG_DEBUG(
"sTgcDigitizationTool::doDigitization hits mapped");
427 double globalHitTime = temp_hit.
globalTime() + eventTime;
429 double bunchTime = globalHitTime - tof;
433 if (digiHits.empty()) {
437 for( std::unique_ptr<sTgcDigit>&
digit : digiHits) {
447 double newTime =
digit->time();
448 int newChannelType = idHelper.channelType(newDigitId);
452 if(newChannelType== sTgcIdHelper::sTgcChannelTypes::Strip)
453 newTime += timeJitterElectronicsStrip;
455 newTime += timeJitterElectronicsPad;
459 newTime += bunchTime;
461 newTime += globalHitTime;
463 double newCharge =
digit->charge();
465 bool isDead{
false},
isPileup{eventId != 0};
466 ATH_MSG_VERBOSE(
"Hit is from the main signal subevent if eventId is zero, eventId = " << eventId <<
" newTime: " << newTime);
472 <<
" BC tag = " << newDigit.
bcTag()
473 <<
" digitTime = " << newDigit.
time()
474 <<
" charge = " << newDigit.
charge()) ;
479 std::vector<MuonSimData::Deposit> deposits;
480 deposits.push_back(std::move(deposit));
485 simData.setPosition(glob_hitOnSurf_wire);
486 simData.setTime(globalHitTime);
487 const unsigned int modHash =
static_cast<unsigned>(
m_idHelperSvc->detElementHash(newDigitId));
488 sTgcSimDigitCont& contToPush = newChannelType == sTgcIdHelper::sTgcChannelTypes::Pad ? unmergedPadDigits :
489 newChannelType == sTgcIdHelper::sTgcChannelTypes::Strip ? unmergedStripDigits : unmergedWireDigits;
491 if (contToPush.size() <= modHash) contToPush.resize(modHash + 1);
492 contToPush[modHash].emplace_back(std::move(
simData), std::move(newDigit));
523 false, outputDigits, *sdoContainer));
528 false, outputDigits, *sdoContainer));
533 if (digits.empty())
continue;
535 const IdentifierHash modHash =
m_idHelperSvc->moduleHash(elemID);
536 std::unique_ptr<sTgcDigitCollection> collection = std::make_unique<sTgcDigitCollection>(elemID, modHash);
537 collection->
insert(collection->
end(), std::make_move_iterator(digits.begin()),
538 std::make_move_iterator(digits.end()));
541 return StatusCode::SUCCESS;
550 if(digitTime > 0) bunchInteger = (
int)(abs(digitTime/25.0));
551 else bunchInteger = (
int)(abs(digitTime/25.0)) + 1;
552 bctag = (bctag | bunchInteger);
553 if(digitTime < 0) bctag = ~bctag;
565 ATH_MSG_ERROR(
"Cannot find retrieve VMM threshold from conditions data base!");
567 ATH_MSG_ERROR(
"Cannot convert VMM charge threshold via conditions data!");
577 rngWrapper->
setSeed( rngName, ctx );
578 CLHEP::HepRandomEngine* engine = rngWrapper->
getEngine(ctx);
586 const double vmmDeadTime,
587 const bool isNeighbourOn,
595 if (digitsInCham.empty())
continue;
598 digitsInCham, isNeighbourOn);
600 if (mergedDigits.empty())
continue;
602 const IdentifierHash
hash =
m_idHelperSvc->moduleHash(mergedDigits.front().identify());
603 const unsigned int hashIdx =
static_cast<unsigned>(
hash);
605 if (
hash >= outDigitContainer.size()) {
606 outDigitContainer.resize(
hash + 1);
610 outSdoContainer.insert(std::make_pair(merged.identify(), std::move(merged.getSimData())));
612 bool acceptDigit{
true};
613 float chargeAfterSmearing = merged.getDigit().charge();
623 if (idHelper.channelType(merged.identify()) == sTgcIdHelper::sTgcChannelTypes::Strip &&
624 chargeAfterSmearing < 0.001) {
627 std::unique_ptr<sTgcDigit> finalDigit = std::make_unique<sTgcDigit>(std::move(merged.getDigit()));
632 " BC tag = " << finalDigit->
bcTag()<<
633 " digitTime = " << finalDigit->
time() <<
634 " charge = " << finalDigit->
charge());
635 outDigitContainer[hashIdx].push_back(std::move(finalDigit));
638 return StatusCode::SUCCESS;
642 const double vmmDeadTime,
644 const bool isNeighborOn)
const {
649 std::stable_sort(unmergedDigits.begin(), unmergedDigits.end(),
651 const int layA = idHelper.gasGap(a.identify());
652 const int layB = idHelper.gasGap(b.identify());
653 if (layA != layB) return layA < layB;
654 const int chA = idHelper.channel(a.identify());
655 const int chB = idHelper.channel(b.identify());
656 if (chA != chB) return chA < chB;
657 return a.time() < b.time();
661 premerged.reserve(unmergedDigits.size());
662 savedDigits.reserve(premerged.capacity());
666 if (!isNeighborOn || savedDigits.empty())
return false;
667 if (savedDigits.back().identify() == candidate.identify() &&
668 std::abs(savedDigits.back().time() - candidate.time()) < vmmDeadTime) {
672 const Identifier digitId = candidate.identify();
673 const int channel = idHelper.channel(digitId);
674 const int maxChannel = detMgr->getsTgcReadoutElement(digitId)->numberOfStrips(digitId);
677 if (neighbour ==
channel)
continue;
678 const Identifier neighbourId = idHelper.channelID(digitId,
679 idHelper.multilayer(digitId),
680 idHelper.gasGap(digitId),
681 idHelper.channelType(digitId), neighbour);
685 return known.identify() == neighbourId &&
686 known.getDigit().charge() > threshold &&
687 std::abs(known.time() - candidate.time()) < m_hitTimeMergeThreshold;
688 }) != savedDigits.end())
return true;
702 sTgcDigit& digit1{(*merge_me).getDigit()};
703 double totalCharge = digit1.
charge();
704 double weightedTime = digit1.time();
707 for ( ; merge_with!= unmergedDigits.end(); ++merge_with) {
709 if ((*merge_with).identify() != (*merge_me).identify()) {
712 const sTgcDigit& mergeDigit{(*merge_with).getDigit()};
718 weightedTime = (weightedTime * totalCharge + mergeDigit.time() * mergeDigit.charge())
719 / (totalCharge + mergeDigit.charge());
721 totalCharge += mergeDigit.
charge();
723 digit1.set_charge(totalCharge);
724 digit1.set_time(weightedTime);
726 if (!savedDigits.empty() &&
727 savedDigits.back().identify() == digit1.identify() &&
728 std::abs(savedDigits.back().time() - digit1.time()) <= vmmDeadTime)
continue;
729 if (digit1.charge() >
threshold || passNeigbourLogic(mergedHit)){
730 savedDigits.emplace_back(std::move(mergedHit));
731 }
else if (isNeighborOn) {
732 premerged.emplace_back(std::move(mergedHit));
735 std::copy_if(std::make_move_iterator(premerged.begin()),
736 std::make_move_iterator(premerged.end()),
737 std::back_inserter(savedDigits), passNeigbourLogic);