22#include "GaudiKernel/SystemOfUnits.h"
23#include "GaudiKernel/PhysicalConstants.h"
25#include "GeoModelHelpers/TransformToStringConverter.h"
45#include "GeoModelKernel/throwExcept.h"
48#include "CLHEP/Random/RandExponential.h"
49#include "CLHEP/Random/RandFlat.h"
50#include "CLHEP/Random/RandGaussZiggurat.h"
66 constexpr int N_Charge = 12;
67 constexpr int N_Velocity = 15;
68 constexpr std::array<double, N_Charge> Charge{0.1, 0.2, 0.3, 0.33, 0.4, 0.5, 0.6, 0.66, 0.7, 0.8, 0.9, 1.0};
69 constexpr std::array<double, N_Velocity> Velocity{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 2.0, 3.0, 10.0, 100.0, 1000.0};
70 constexpr double Eff_garfield[N_Charge][N_Velocity] = {
71 {0.8648, 0.3476, 0.1407, 0.0618, 0.0368, 0.0234, 0.0150, 0.0120, 0.0096, 0.0079, 0.0038, 0.0041, 0.0035, 0.0049, 0.0054},
72 {0.9999, 0.9238, 0.6716, 0.4579, 0.3115, 0.2238, 0.1727, 0.1365, 0.1098, 0.0968, 0.0493, 0.0451, 0.0528, 0.0694, 0.0708},
73 {1.0000, 0.9978, 0.9517, 0.8226, 0.6750, 0.5611, 0.4674, 0.3913, 0.3458, 0.3086, 0.1818, 0.1677, 0.1805, 0.2307, 0.2421},
74 {1.0000, 0.9994, 0.9758, 0.8918, 0.7670, 0.6537, 0.5533, 0.4856, 0.4192, 0.3852, 0.2333, 0.2186, 0.2479, 0.2957, 0.2996},
75 {1.0000, 1.0000, 0.9972, 0.9699, 0.9022, 0.8200, 0.7417, 0.6660, 0.6094, 0.5622, 0.3846, 0.3617, 0.3847, 0.4578, 0.4583},
76 {1.0000, 1.0000, 0.9998, 0.9956, 0.9754, 0.9479, 0.9031, 0.8604, 0.8126, 0.7716, 0.5827, 0.5545, 0.5865, 0.6834, 0.6706},
77 {1.0000, 1.0000, 1.0000, 0.9997, 0.9968, 0.9876, 0.9689, 0.9464, 0.9221, 0.8967, 0.7634, 0.7385, 0.7615, 0.8250, 0.8309},
78 {1.0000, 1.0000, 1.0000, 1.0000, 0.9995, 0.9952, 0.9866, 0.9765, 0.9552, 0.9427, 0.8373, 0.8127, 0.8412, 0.8899, 0.8891},
79 {1.0000, 1.0000, 1.0000, 1.0000, 0.9995, 0.9981, 0.9918, 0.9803, 0.9754, 0.9602, 0.8730, 0.8564, 0.8746, 0.9178, 0.9261},
80 {1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 0.9993, 0.9990, 0.9951, 0.9935, 0.9886, 0.9419, 0.9277, 0.9422, 0.9686, 0.9700},
81 {1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 0.9998, 0.9996, 0.9980, 0.9966, 0.9786, 0.9718, 0.9748, 0.9875, 0.9882},
82 {1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 0.9998, 1.0000, 0.9991, 0.9988, 0.9913, 0.9872, 0.9917, 0.9970, 0.9964}};
84 validIndex(
int idx,
int arraySize){
85 return (idx>=0) and (idx<arraySize);
91 constexpr double SIG_VEL = 4.8;
142 return StatusCode::FAILURE;
159 ATH_MSG_DEBUG(
"Ready to read parameters for cluster simulation from file");
177 return StatusCode::SUCCESS;
183 SmartIF<IGeoModelSvc> geoModel{Gaudi::svcLocator()->service(
"GeoModelSvc")};
186 return StatusCode::FAILURE;
190 std::string atlasVersion = geoModel->atlasVersion();
192 SmartIF<IRDBAccessSvc> rdbAccess{Gaudi::svcLocator()->service(
"RDBAccessSvc")};
195 return StatusCode::FAILURE;
201 std::string configVal =
"";
203 IRDBRecordset_ptr atlasCommonRec = rdbAccess->getRecordsetPtr(
"AtlasCommon", atlasVersion,
"ATLAS");
204 if (atlasCommonRec->
size() == 0) {
207 configVal = (*atlasCommonRec)[0]->getString(
"CONFIG");
208 ATH_MSG_INFO(
"From DD Database, Configuration is " << configVal);
209 if (configVal ==
"RUN1") {
211 }
else if (configVal ==
"RUN2") {
213 }
else if (configVal ==
"RUN3") {
215 }
else if (configVal ==
"RUN4") {
218 if (
run == DataPeriod::Unknown) {
219 ATH_MSG_FATAL(
"Unexpected value for geometry config read from the database: " << configVal);
220 return StatusCode::FAILURE;
227 ATH_MSG_INFO(
"From Geometry DB: MuonSpectrometer configuration is: RUN1 or MuonGeometry = R.06");
229 ATH_MSG_INFO(
"From Geometry DB: MuonSpectrometer configuration is: RUN2 or MuonGeometry = R.07");
230 else if (
run == Run3)
231 ATH_MSG_INFO(
"From Geometry DB: MuonSpectrometer configuration is: RUN3 or MuonGeometry = R.09");
232 else if (
run == Run4)
233 ATH_MSG_INFO(
"From Geometry DB: MuonSpectrometer configuration is: RUN4 or MuonGeometry = R.10");
246 if (configVal ==
"RUN1") {
265 ATH_MSG_INFO(
"Run3/4: configuration parameter not from COOL");
272 ATH_MSG_INFO(
"RPC Run1/2/3-dependent configuration is enforced");
274 ATH_MSG_WARNING(
"Run1/2/3-dependent configuration is bypassed; be careful with option settings");
285 return StatusCode::SUCCESS;
288template <
class CondType>
291 const CondType* & condPtr)
const {
294 ATH_MSG_DEBUG(
"No key has been configured for object "<<
typeid(CondType).name()<<
". Clear pointer");
296 return StatusCode::SUCCESS;
300 ATH_MSG_FATAL(
"Failed to load conditions object "<<key.fullKey()<<
".");
301 return StatusCode::FAILURE;
303 condPtr = readHandle.
cptr();
304 return StatusCode::SUCCESS;
313 m_thpcRPC = std::make_unique<TimedHitCollection<RPCSimHit>>();
316 return StatusCode::SUCCESS;
324 TimedHitCollList hitCollList;
327 hitCollList.empty()) {
329 return StatusCode::FAILURE;
334 TimedHitCollList::iterator iColl(hitCollList.begin());
335 TimedHitCollList::iterator endColl(hitCollList.end());
338 for (; iColl != endColl; ++iColl) {
342 ATH_MSG_DEBUG(
"RPCSimHitCollection found with " << hitCollPtr->
size() <<
" hits");
345 m_thpcRPC->insert(timeIndex, hitCollPtr);
349 return StatusCode::SUCCESS;
366 if (!hitCollection.
isValid()) {
367 ATH_MSG_ERROR(
"Could not get RPCSimHitCollection container " << hitCollection.
name() <<
" from store "
368 << hitCollection.
store());
369 return StatusCode::FAILURE;
373 m_thpcRPC = std::make_unique<TimedHitCollection<RPCSimHit>>(1);
375 ATH_MSG_DEBUG(
"RPCSimHitCollection found with " << hitCollection->size() <<
" hits");
377 return StatusCode::SUCCESS;
380 TimedHitCollList hitCollList;
384 return StatusCode::FAILURE;
386 if (hitCollList.empty()) {
388 return StatusCode::FAILURE;
394 m_thpcRPC = std::make_unique<TimedHitCollection<RPCSimHit>>();
396 TimedHitCollList::iterator iColl(hitCollList.begin());
397 TimedHitCollList::iterator endColl(hitCollList.end());
398 while (iColl != endColl) {
400 m_thpcRPC->insert(iColl->first, p_collection);
405 return StatusCode::SUCCESS;
410 StatusCode status = StatusCode::SUCCESS;
420 ATH_CHECK(sdoContainer.
record(std::make_unique<MuonSimDataCollection>()));
429 if (status.isFailure()) {
ATH_MSG_ERROR(
"doDigitization Failed"); }
430 for (
size_t coll_hash = 0; coll_hash < collections.size(); ++coll_hash) {
431 if (collections[coll_hash]) {
432 ATH_CHECK( digitContainer->addCollection (collections[coll_hash].release(), coll_hash) );
444 StatusCode status = StatusCode::SUCCESS;
457 ATH_CHECK(sdoContainer.
record(std::make_unique<MuonSimDataCollection>()));
466 if (StatusCode::FAILURE == status) {
474 for (
size_t coll_hash = 0; coll_hash < collections.size(); ++coll_hash) {
475 if (collections[coll_hash]) {
476 ATH_CHECK( digitContainer->addCollection (collections[coll_hash].release(), coll_hash) );
488 rngWrapper->
setSeed(name(), ctx);
489 CLHEP::HepRandomEngine* rndmEngine = rngWrapper->
getEngine(ctx);
495 std::unique_ptr<RPCSimHitCollection> inputSimHitColl{std::make_unique<RPCSimHitCollection>(
"RPC_Hits")};
505 return StatusCode::FAILURE;
508 struct SimDataContent {
510 std::vector<MuonSimData::Deposit> deposits;
515 while (
m_thpcRPC->nextDetectorElement(i, e)) {
518 std::map<Identifier, SimDataContent> channelSimDataMap;
529 const int idHit =
hit.RPCid();
531 const double globalHitTime{
hitTime(phit)};
533 const double G4Time{
hit.globalTime()};
535 const double bunchTime{globalHitTime -
hit.globalTime()};
537 ATH_MSG_DEBUG(
"Global time " << globalHitTime <<
" G4 time " << G4Time <<
" Bunch time " << bunchTime);
540 ATH_MSG_VERBOSE(
"Validation: globalHitTime, G4Time, BCtime = " << globalHitTime <<
" " << G4Time <<
" " << bunchTime);
541 inputSimHitColl->Emplace(idHit, globalHitTime,
hit.localPosition(),
543 hit.postLocalPosition(),
544 hit.energyDeposit(),
hit.stepLength(),
hit.particleEncoding(),
hit.kineticEnergy());
548 const std::string stationName =
m_muonHelper->GetStationName(idHit);
550 const int stationPhi =
m_muonHelper->GetPhiSector(idHit);
553 const int doubletPhi =
m_muonHelper->GetDoubletPhi(idHit);
562 ATH_MSG_WARNING(
"Failed to construct the element ID from "<<stationName
563 <<
", stationEta: "<<stationEta<<
", stationPhi: "<<stationPhi<<
", doubletR: "<<doubletR);
568 <<
" stationName " << stationName <<
" stationEta " << stationEta <<
" stationPhi " << stationPhi <<
" doubletR "
569 << doubletR <<
" doubletZ " << doubletZ <<
" doubletPhi " << doubletPhi <<
" gasGap " << gasGap);
577 gasGap = gasGap == 1 ? 2 : 1;
581 bool isValidEta{
false}, isValidPhi{
false};
582 const Identifier idpaneleta =
m_idHelper->channelID(elementID, doubletZ, doubletPhi, gasGap, 0, 1, isValidEta);
583 const Identifier idpanelphi =
m_idHelper->channelID(elementID, doubletZ, doubletPhi, gasGap, 1, 1, isValidPhi);
584 if (!isValidEta || !isValidPhi) {
586 <<
" stationName " << stationName <<
" stationEta " << stationEta <<
" stationPhi " << stationPhi
587 <<
" doubletR " << doubletR <<
" doubletZ " << doubletZ <<
" doubletPhi " << doubletPhi <<
" gasGap "
596 const double corrtimejitter = tmp_CorrJitter > 0.01 ?
597 CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0., tmp_CorrJitter) : 0.;
607 std::array<int, 3> pcseta =
physicalClusterSize(ctx, reEle, idpaneleta, gapCentre, rndmEngine);
608 ATH_MSG_VERBOSE(
"Simulated cluster on eta panel: size/first/last= " << pcseta[0] <<
"/" << pcseta[1] <<
"/" << pcseta[2]);
609 std::array<int, 3> pcsphi =
physicalClusterSize(ctx, reEle, idpanelphi, gapCentre, rndmEngine);
610 ATH_MSG_VERBOSE(
"Simulated cluster on phi panel: size/first/last= " << pcsphi[0] <<
"/" << pcsphi[1] <<
"/" << pcsphi[2]);
615 const Identifier atlasRpcIdeta =
m_idHelper->channelID(elementID, doubletZ, doubletPhi, gasGap, 0, pcseta[1], isValidEta);
616 const Identifier atlasRpcIdphi =
m_idHelper->channelID(elementID, doubletZ, doubletPhi, gasGap, 1, pcsphi[1], isValidPhi);
619 const auto [etaStripOn, phiStripOn] =
detectionEfficiency(ctx, idpaneleta, idpanelphi, rndmEngine, particleLink);
620 ATH_MSG_DEBUG(
"SetPhiOn " << phiStripOn <<
" SetEtaOn " << etaStripOn);
622 for (
bool imeasphi : {
false,
true}) {
623 if (!imeasphi && (!etaStripOn || !isValidEta))
continue;
624 if (imeasphi && (!phiStripOn || !isValidPhi))
continue;
628 const Identifier& atlasId = !imeasphi ? atlasRpcIdeta : atlasRpcIdphi;
629 std::array<int, 3> pcs{!imeasphi ? pcseta : pcsphi};
631 ATH_MSG_DEBUG(
"SetOn: stationName " << stationName <<
" stationEta " << stationEta <<
" stationPhi " << stationPhi
632 <<
" doubletR " << doubletR <<
" doubletZ " << doubletZ <<
" doubletPhi " << doubletPhi
633 <<
" gasGap " << gasGap <<
" measphi " << imeasphi);
641 ATH_MSG_DEBUG(
"Simulated cluster1: size/first/last= " << pcs[0] <<
"/" << pcs[1] <<
"/" << pcs[2]);
648 <<
" hit "<<
m_idHelper->print_to_string(atlasId)
660 double tns = G4Time + proptime + corrtimejitter;
661 ATH_MSG_VERBOSE(
"TOF+propagation time " << tns <<
" /s where proptime " << proptime <<
"/s");
663 double time = tns + bunchTime;
667 long long int packedMCword =
PackMCTruth(proptime, bunchTime, pos.y(), pos.z());
669 double* b =
reinterpret_cast<double*
>(&packedMCword);
680 if (std::abs(
hit.particleEncoding()) == 13 ||
hit.particleEncoding() == 0) {
681 if (channelSimDataMap.find(atlasId) == channelSimDataMap.end()) {
682 SimDataContent& content = channelSimDataMap[atlasId];
683 content.channelId = atlasId;
684 content.deposits.push_back(deposit);
685 content.gpos = reEle->
transform(atlasId)*
687 content.simTime =
hitTime(phit);
688 ATH_MSG_VERBOSE(
"adding SDO entry: r " << content.gpos.perp() <<
" z " << content.gpos.z());
700 for (
int clus = pcs[1]; clus <= pcs[2]; ++clus) {
701 Identifier newId =
m_idHelper->channelID(stationName, stationEta, stationPhi, doubletR, doubletZ,
702 doubletPhi, gasGap, imeasphi, clus,
isValid);
704 ATH_MSG_WARNING(__FILE__<<
":"<<__LINE__<<
"Channel "<< stationName<<
" "<<stationEta<<
" "<<stationPhi<<
" "<< doubletR<<
" "<<doubletZ
705 <<
" "<< doubletPhi<<
" "<< gasGap <<
" "<< imeasphi<<
" "<< clus<<
" is invalid");
710 if (stationName.find(
"BI") != std::string::npos) {
711 ATH_MSG_WARNING(
"Temporary skipping creation of RPC digit for stationName="
712 << stationName <<
", eta=" << stationEta <<
", phi=" << stationPhi <<
", doubletR=" << doubletR
713 <<
", doubletZ=" << doubletZ <<
", doubletPhi=" << doubletPhi <<
", gasGap=" << gasGap
714 <<
", measuresPhi=" << imeasphi <<
", strip=" << clus <<
", cf. ATLASRECTS-6124");
715 return StatusCode::SUCCESS;
719 return StatusCode::FAILURE;
728 std::vector<MuonSimData::Deposit> newdeps;
729 newdeps.push_back(deposit);
739 for (
auto it = channelSimDataMap.begin(); it != channelSimDataMap.end(); ++it) {
741 simData.setPosition(it->second.gpos);
742 simData.setTime(it->second.simTime);
743 auto insertResult = sdoContainer->insert(std::make_pair(it->first,
simData));
744 if (!insertResult.second)
745 ATH_MSG_WARNING(
"Attention: this sdo is not recorded, since the identifier already exists in the sdoContainer map");
761 const std::vector<MuonSimData::Deposit> theDeps = (*map_iter).second;
765 std::multimap<double, MuonSimData::Deposit> times;
768 for (
unsigned int k = 0; k < theDeps.size(); k++) {
769 double time = theDeps[k].second.secondEntry();
770 times.insert(std::multimap<double, MuonSimData::Deposit>::value_type(time, theDeps[k]));
777 std::multimap<double, MuonSimData::Deposit>::iterator map_dep_iter = times.begin();
780 double last_time = -10000;
781 for (; map_dep_iter != times.end(); ++map_dep_iter) {
782 double currTime = (*map_dep_iter).first;
788 if (sdoContainer->find(theId) != sdoContainer->end())
790 std::map<Identifier, MuonSimData>::const_iterator it = sdoContainer->find(theId);
791 std::vector<MuonSimData::Deposit> deps = ((*it).second).getdeposits();
792 deps.push_back((*map_dep_iter).second);
795 std::vector<MuonSimData::Deposit> deposits;
796 deposits.push_back((*map_dep_iter).second);
797 std::pair<std::map<Identifier, MuonSimData>::iterator,
bool> insertResult =
798 sdoContainer->insert(std::make_pair(theId,
MuonSimData(deposits, 0)));
799 if (!insertResult.second)
801 "Attention TEMP: this sdo is not recorded, since the identifier already exists in the sdoContainer map");
805 if (std::abs(currTime - last_time) > (
m_deadTime)) {
806 ATH_MSG_DEBUG(
"deposit with time " << currTime <<
" is distant enough from previous (if any) hit on teh same strip");
807 last_time = (*map_dep_iter).first;
810 double uncorrjitter = 0;
813 if (tmp_UncorrJitter > 0.01) uncorrjitter = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0., tmp_UncorrJitter);
823 double newDigit_time = currTime + uncorrjitter +
m_rpc_time_shift - tp - propTimeFromStripCenter;
825 double digi_ToT = -1.;
828 ATH_MSG_VERBOSE(
"last_time=currTime " << last_time <<
" jitter " << uncorrjitter <<
" TOFcorrection " << tp <<
" shift "
832 bool outsideDigitizationWindow =
outsideWindow(newDigit_time);
833 if (outsideDigitizationWindow) {
834 ATH_MSG_VERBOSE(
"hit outside digitization window - do not produce digits");
843 last_time = (*map_dep_iter).first;
845 std::unique_ptr<RpcDigit> newDigit = std::make_unique<RpcDigit>(theId, newDigit_time, digi_ToT,
false);
851 if (
m_idHelper->get_hash(elemId, coll_hash, &rpcContext)) {
852 ATH_MSG_ERROR(
"Unable to get RPC hash id from RPC Digit collection "
853 <<
"context begin_index = " << rpcContext.
begin_index()
854 <<
" context end_index = " << rpcContext.
end_index() <<
" the identifier is \n"<<elemId);
861 if (coll_hash >= collections.size()) {
862 collections.resize (coll_hash+1);
864 digitCollection = collections[coll_hash].
get();
865 if (!digitCollection) {
866 collections[coll_hash] = std::make_unique<RpcDigitCollection>(elemId, coll_hash);
867 digitCollection = collections[coll_hash].
get();
869 digitCollection->
push_back(std::move(newDigit));
873 if (sdoContainer->find(theId) != sdoContainer->end()) {
874 std::map<Identifier, MuonSimData>::const_iterator it = sdoContainer->find(theId);
875 std::vector<MuonSimData::Deposit> deps = ((*it).second).getdeposits();
876 deps.push_back((*map_dep_iter).second);
878 std::vector<MuonSimData::Deposit> deposits;
879 deposits.push_back((*map_dep_iter).second);
880 std::pair<std::map<Identifier, MuonSimData>::iterator,
bool> insertResult =
881 sdoContainer->insert(std::make_pair(theId,
MuonSimData(deposits, 0)));
882 if (!insertResult.second)
884 "Attention: this sdo is not recorded, since teh identifier already exists in the sdoContainer map");
889 ATH_MSG_DEBUG(
"discarding digit due to dead time: " << (*map_dep_iter).first <<
" " << last_time);
901 return StatusCode::SUCCESS;
918 (flip ?
Amg::getRotateY3D(180.*Gaudi::Units::deg) : Amg::Transform3D::Identity())};
929 CLHEP::HepRandomEngine* rndmEngine)
const {
932 std::array<int, 3> result{};
936 const int doubletPhi =
m_idHelper->doubletPhi(
id);
938 const bool measuresPhi =
m_idHelper->measuresPhi(
id);
939 const double pitch= ele->
StripPitch(measuresPhi);
942 const int nstrip = ele->
stripNumber(position.block<2,1>(0,0),
id);
943 const int numStrips = ele->
Nstrips(measuresPhi);
948 if (nstrip < 1 || nstrip > numStrips) {
952 float xstripnorm = (locStripPos -position).
x() / pitch ;
965 std::array<int, 3>&& pcs,
973 }
else if (pcs[0] == 2) {
975 }
else if (pcs[0] > 2) {
976 pcs[1] = pcs[1] - pcs[0] / 2;
977 if (fmod(pcs[0], 2) == 0) pcs[1] = pcs[1] + 1;
978 pcs[2] = pcs[1] + pcs[0] - 1;
979 }
else if (pcs[0] < -2) {
980 pcs[1] = pcs[1] + pcs[0] / 2;
981 pcs[2] = pcs[1] - pcs[0] - 1;
986 pcs[1] = std::clamp(pcs[1], 1, nstrips);
987 pcs[2] = std::clamp(pcs[2], 1, nstrips);
989 pcs[0] = pcs[2] - pcs[1] + 1;
1007 return std::abs(distance * SIG_VEL * 1.e-3);
1014 ATH_MSG_WARNING(
"A poblem: packing a propagation time <0 " << proptime <<
" redefine it as 0");
1017 long long int new_proptime = int(proptime * 10) & 0xff;
1023 long long int new_bctime = int((bctime + 300.) * 10.) & 0xffff;
1028 long long int new_posy = int((posy + 1500.) * 10.) & 0xffff;
1033 long long int new_posz = int((posz + 1500.) * 10.) & 0xffff;
1035 return (new_proptime + (new_bctime << 8) + (new_posy << 24) + (new_posz << 40));
1041 using Repacker =
union
1049 MCTruth.dWord = theWord;
1050 proptime = ((MCTruth.iWord) & 0x00000000000000ffLL) / 10.;
1051 bctime = (((MCTruth.iWord) & 0x0000000000ffff00LL) >> 8) / 10.;
1052 posy = (((MCTruth.iWord) & 0x000000ffff000000LL) >> 24) / 10.;
1053 posz = (((MCTruth.iWord) & 0x00ffff0000000000LL) >> 40) / 10.;
1056 bctime = bctime - 300.;
1057 posy = posy - 1500.;
1058 posz = posz - 1500.;
1064 SmartIF<ITagInfoMgr> tagInfoMgr{Gaudi::svcLocator()->service(
"TagInfoMgr")};
1065 if (!tagInfoMgr) {
return StatusCode::FAILURE; }
1067 std::string RpctimeSchema =
"";
1068 std::stringstream RpctimeShift;
1072 RpctimeSchema =
"Datalike_TOFoff_TimeShift" + RpctimeShift.str() +
"nsec";
1074 RpctimeSchema =
"G4like_TOFon_TimeShift" + RpctimeShift.str() +
"nsec";
1079 if (
sc.isFailure()) {
1086 return StatusCode::SUCCESS;
1094 CLHEP::HepRandomEngine* rndmEngine,
1099 ATH_MSG_DEBUG(
"RpcDigitizationTool::in DetectionEfficiency");
1107 float maxGeomEff{0.99}, PhiAndEtaEff{0.99}, OnlyEtaEff{0.f}, OnlyPhiEff{0.f};
1110 int stationName =
m_idHelper->stationName(IdEta);
1111 int stationEta =
m_idHelper->stationEta(IdEta);
1116 return std::make_pair(
false,
false);
1121 return std::make_pair(
true,
true);
1123 bool etaStripOn{
true}, phiStripOn{
true};
1128 unsigned int index = stationName - 2;
1130 if (stationName > 5 && stationName < 50)
index =
index - 2;
1132 else if (stationName > 50)
1138 THROW_EXCEPTION(
"Index out of array in Detection Efficiency SideA " <<
index <<
" stationName = " << stationName);
1145 if (stationEta < 0) {
1147 THROW_EXCEPTION(
"Index out of array in Detection Efficiency SideC " <<
index <<
" stationName = " << stationName);
1164 ATH_MSG_DEBUG(
"Efficiencies and cluster size + dead strips will be extracted from COOL");
1166 double FracDeadStripEta{0.}, FracDeadStripPhi{0.};
1167 double EtaPanelEfficiency{1.}, PhiPanelEfficiency{1.}, GapEfficiency{1.};
1168 int RPC_ProjectedTracksEta = 0;
1170 std::optional<double> fracDeadStripEtaFromCOOL = readCdo->
getFracDeadStrip(IdEta);
1171 std::optional<double> fracDeadStripPhiFromCOOL = readCdo->
getFracDeadStrip(IdPhi);
1173 bool noEntryInDb = !fracDeadStripEtaFromCOOL || !fracDeadStripPhiFromCOOL;
1175 FracDeadStripEta = fracDeadStripEtaFromCOOL.value_or(0.);
1176 FracDeadStripPhi = fracDeadStripPhiFromCOOL.value_or(0.);
1179 EtaPanelEfficiency = readCdo->
getEfficiency(IdEta).value_or(1.);
1180 PhiPanelEfficiency = readCdo->
getEfficiency(IdPhi).value_or(1.);
1183 if (std::abs(FracDeadStripEta - 1.) < 0.001) {
1184 ATH_MSG_DEBUG(
"Watch out: SPECIAL CASE: Read from Cool: FracDeadStripEta/Phi "
1185 << FracDeadStripEta <<
"/" << FracDeadStripPhi <<
" RPC_ProjectedTracksEta " << RPC_ProjectedTracksEta
1186 <<
" Eta/PhiPanelEfficiency " << EtaPanelEfficiency <<
"/" << PhiPanelEfficiency <<
" gapEff " << GapEfficiency
1190 FracDeadStripPhi = 0.;
1191 ATH_MSG_VERBOSE(
"Watch out: SPECIAL CASE: Resetting FracDeadStripPhi " << FracDeadStripPhi <<
" ignoring phi dead strips ");
1199 bool changing =
false;
1200 ATH_MSG_DEBUG(
"Read from Cool: FracDeadStripEta/Phi " << FracDeadStripEta <<
"/" << FracDeadStripPhi <<
" RPC_ProjectedTracksEta "
1201 << RPC_ProjectedTracksEta <<
" Eta/PhiPanelEfficiency " << EtaPanelEfficiency
1202 <<
"/" << PhiPanelEfficiency <<
" gapEff " << GapEfficiency);
1204 if ((maxGeomEff - FracDeadStripEta) - EtaPanelEfficiency < -0.011) {
1205 ATH_MSG_DEBUG(
"Ineff. from dead strips on Eta Panel larger that measured efficiency: deadFrac="
1206 << FracDeadStripEta <<
" Panel Eff=" << EtaPanelEfficiency <<
" for Panel " <<
m_idHelper->show_to_string(IdEta));
1207 ATH_MSG_DEBUG(
"... see the corresponding report from RpcDetectorStatusDbTool");
1209 EtaPanelEfficiency = maxGeomEff - FracDeadStripEta;
1213 if ((maxGeomEff - FracDeadStripPhi) - PhiPanelEfficiency < -0.011) {
1214 ATH_MSG_DEBUG(
"Ineff. from dead strips on Phi Panel larger that measured efficiency: deadFrac="
1215 << FracDeadStripPhi <<
" Panel Eff=" << PhiPanelEfficiency <<
" for Panel " <<
m_idHelper->show_to_string(IdPhi));
1216 ATH_MSG_DEBUG(
"... see the corresponding report among the warnings of RpcDetectorStatusDbTool");
1218 PhiPanelEfficiency = maxGeomEff - FracDeadStripPhi;
1222 if ((maxGeomEff - FracDeadStripEta * FracDeadStripPhi) - GapEfficiency < -0.011) {
1223 ATH_MSG_DEBUG(
"Ineff. from dead strips on Eta/Phi Panels larger that measured EtaORPhi efficiency: deadFrac="
1224 << FracDeadStripEta * FracDeadStripPhi <<
" EtaORPhi Eff=" << GapEfficiency <<
" for GasGap "
1226 ATH_MSG_DEBUG(
"... see the corresponding report among the warnings of RpcDetectorStatusDbTool");
1228 GapEfficiency = maxGeomEff - FracDeadStripEta * FracDeadStripPhi;
1232 ATH_MSG_DEBUG(
"Rinormalized Values from Cool: FracDeadStripEta/Phi "
1233 << FracDeadStripEta <<
"/" << FracDeadStripPhi <<
" RPC_ProjectedTracksEta " << RPC_ProjectedTracksEta
1234 <<
" Eta/PhiPanelEfficiency " << EtaPanelEfficiency <<
"/" << PhiPanelEfficiency <<
" gapEff " << GapEfficiency);
1238 if ((FracDeadStripEta > 0.0 && FracDeadStripEta < 1.0) || (FracDeadStripPhi > 0.0 && FracDeadStripPhi < 1.0) || (noEntryInDb)) {
1239 EtaPanelEfficiency = EtaPanelEfficiency / (maxGeomEff - FracDeadStripEta);
1240 PhiPanelEfficiency = PhiPanelEfficiency / (maxGeomEff - FracDeadStripPhi);
1241 GapEfficiency = GapEfficiency / (maxGeomEff - FracDeadStripEta * FracDeadStripPhi);
1243 if (EtaPanelEfficiency > maxGeomEff) EtaPanelEfficiency = maxGeomEff;
1244 if (PhiPanelEfficiency > maxGeomEff) PhiPanelEfficiency = maxGeomEff;
1245 if (GapEfficiency > maxGeomEff) GapEfficiency = maxGeomEff;
1247 if (EtaPanelEfficiency > GapEfficiency) GapEfficiency = EtaPanelEfficiency;
1248 if (PhiPanelEfficiency > GapEfficiency) GapEfficiency = PhiPanelEfficiency;
1249 ATH_MSG_DEBUG(
"Eff Redefined (to correct for deadfrac): FracDeadStripEta/Phi "
1250 <<
" Eta/PhiPanelEfficiency " << EtaPanelEfficiency <<
"/" << PhiPanelEfficiency <<
" gapEff "
1256 PhiAndEtaEff = float(EtaPanelEfficiency + PhiPanelEfficiency - GapEfficiency);
1257 if (PhiAndEtaEff < 0.) PhiAndEtaEff = 0.;
1258 OnlyEtaEff = float(EtaPanelEfficiency - PhiAndEtaEff);
1259 if (OnlyEtaEff < 0.) OnlyEtaEff = 0.;
1260 OnlyPhiEff = float(PhiPanelEfficiency - PhiAndEtaEff);
1261 if (OnlyPhiEff < 0.) OnlyPhiEff = 0.;
1265 bool applySpecialPatch =
false;
1271 applySpecialPatch =
true;
1273 "Applying special patch for BMS at |eta|=6 lowPt plane -dbbZ=2 and dbPhi=1 ... will use default eff. for Id "
1276 "Applying special patch: THIS HAS TO BE DONE IF /RPC/DQMF/ELEMENT_STATUS tag is "
1277 "RPCDQMFElementStatus_2012_Jaunuary_2");
1283 if (applySpecialPatch || RPC_ProjectedTracksEta < m_CutProjectedTracks || RPC_ProjectedTracksEta > 10000000 ||
1284 EtaPanelEfficiency > 1 || EtaPanelEfficiency < 0 || PhiPanelEfficiency > 1 || PhiPanelEfficiency < 0 || GapEfficiency > 1 ||
1285 GapEfficiency < 0) {
1287 THROW_EXCEPTION(
"Index out of array in Detection Efficiency SideA COOLDB" <<
index <<
" stationName = " << stationName);
1291 <<
" resetting eff. from cool with default(python) values ");
1297 if (stationEta < 0) {
1299 THROW_EXCEPTION(
"Index out of array in Detection Efficiency SideC COOLDB" <<
index <<
" stationName = " << stationName);
1308 float effgap = PhiAndEtaEff + OnlyEtaEff + OnlyPhiEff;
1309 float s_EtaPanelEfficiency = 1. - FracDeadStripEta;
1310 float s_PhiPanelEfficiency = 1. - FracDeadStripPhi;
1311 float s_PhiAndEtaEff = s_EtaPanelEfficiency * s_PhiPanelEfficiency / effgap;
1312 if (s_PhiAndEtaEff < PhiAndEtaEff) PhiAndEtaEff = s_PhiAndEtaEff;
1313 float s_OnlyEtaEff = s_EtaPanelEfficiency - PhiAndEtaEff;
1314 float s_OnlyPhiEff = s_PhiPanelEfficiency - PhiAndEtaEff;
1316 if (s_OnlyEtaEff < OnlyEtaEff) OnlyEtaEff = s_OnlyEtaEff;
1317 if (s_OnlyPhiEff < OnlyPhiEff) OnlyPhiEff = s_OnlyPhiEff;
1321 float VolEff = PhiAndEtaEff + OnlyEtaEff + OnlyPhiEff;
1322 if (VolEff > maxGeomEff) {
1323 PhiAndEtaEff = (PhiAndEtaEff / VolEff) * maxGeomEff;
1324 OnlyEtaEff = (OnlyEtaEff / VolEff) * maxGeomEff;
1325 OnlyPhiEff = (OnlyPhiEff / VolEff) * maxGeomEff;
1338 PhiAndEtaEff = PhiAndEtaEff * eff_sf;
1339 OnlyEtaEff = OnlyEtaEff * eff_sf;
1340 OnlyPhiEff = OnlyPhiEff * eff_sf;
1344 float I0 = PhiAndEtaEff;
1345 float I1 = PhiAndEtaEff + OnlyEtaEff;
1346 float ITot = PhiAndEtaEff + OnlyEtaEff + OnlyPhiEff;
1348 float GapEff = ITot ;
1349 float PhiEff = PhiAndEtaEff + OnlyPhiEff;
1350 float EtaEff = PhiAndEtaEff + OnlyEtaEff;
1352 ATH_MSG_DEBUG(
"DetectionEfficiency: Final Efficiency Values applied for "
1353 <<
m_idHelper->show_to_string(IdEta) <<
" are " << PhiAndEtaEff <<
"=PhiAndEtaEff " << OnlyEtaEff
1354 <<
"=OnlyEtaEff " << OnlyPhiEff <<
"=OnlyPhiEff " << GapEff <<
"=GapEff " << EtaEff <<
"=EtaEff " << PhiEff
1357 float rndmEff = CLHEP::RandFlat::shoot(rndmEngine, 1);
1362 }
else if ((I0 <= rndmEff) && (rndmEff < I1)) {
1365 }
else if ((I1 <= rndmEff) && (rndmEff <= ITot)) {
1373 return std::make_pair(etaStripOn, phiStripOn);
1380 CLHEP::HepRandomEngine* rndmEngine)
const {
1381 ATH_MSG_DEBUG(
"RpcDigitizationTool::in determineClusterSize");
1385 int ClusterSize = 1;
1387 double FracClusterSize1{1.}, FracClusterSize2{0.}, MeanClusterSize{1.},
1388 FracClusterSizeTail{0.}, MeanClusterSizeTail{1.},
1389 FracClusterSize2norm{0.};
1392 int stationName =
m_idHelper->stationName(idRpcStrip);
1393 int stationEta =
m_idHelper->stationEta(idRpcStrip);
1394 int measuresPhi =
m_idHelper->measuresPhi(idRpcStrip);
1396 unsigned int index = stationName - 2;
1398 if (stationName > 5 && stationName < 50)
index =
index - 2;
1400 else if (stationName > 50)
1410 ATH_MSG_ERROR(
"Index out of array in determineClusterSize SideA " <<
index <<
" statName " << stationName);
1418 if (stationEta < 0) {
1424 ATH_MSG_ERROR(
"Index out of array in determineClusterSize SideC " <<
index <<
" statName " << stationName);
1449 ATH_MSG_DEBUG(
"FracClusterSize1 and 2 " << FracClusterSize1 <<
" " << FracClusterSize2);
1451 FracClusterSizeTail = 1. - FracClusterSize1 - FracClusterSize2;
1453 MeanClusterSizeTail = MeanClusterSize - FracClusterSize1 - 2 * FracClusterSize2;
1455 ATH_MSG_DEBUG(
"MeanClusterSizeTail and FracClusterSizeTail " << MeanClusterSizeTail <<
" " << FracClusterSizeTail);
1458 if (RPC_ProjectedTracks < m_CutProjectedTracks || RPC_ProjectedTracks > 10000000 || MeanClusterSize >
m_CutMaxClusterSize ||
1459 MeanClusterSize <= 1 || FracClusterSizeTail < 0 || FracClusterSize1 < 0 || FracClusterSize2 < 0 || FracClusterSizeTail > 1 ||
1460 FracClusterSize1 > 1 || FracClusterSize2 > 1) {
1461 if (stationName >= 2) {
1467 ATH_MSG_ERROR(
"Index out of array in determineClusterSize SideA " <<
index <<
" statName " << stationName);
1475 if (stationEta < 0) {
1479 ATH_MSG_ERROR(
"Index out of array in determineClusterSize SideC " <<
index <<
" statName " << stationName);
1496 FracClusterSize1 = std::min(FracClusterSize1, 1.);
1497 FracClusterSize2 = std::min(FracClusterSize2, 1.);
1498 FracClusterSizeTail = std::min(FracClusterSizeTail, 1.);
1499 float FracTot = FracClusterSize1 + FracClusterSize2 + FracClusterSizeTail;
1500 if (FracTot != 1. && FracTot > 0) {
1501 FracClusterSize1 = FracClusterSize1 / FracTot;
1502 FracClusterSize2 = FracClusterSize2 / FracTot;
1503 FracClusterSizeTail = FracClusterSizeTail / FracTot;
1505 if (MeanClusterSizeTail < 0 || MeanClusterSizeTail > 10) MeanClusterSizeTail = 1;
1507 ATH_MSG_VERBOSE(
"ClusterSize Final " << FracClusterSize1 <<
" FracClusterSize1 " << FracClusterSize2 <<
" FracClusterSize2 "
1508 << FracClusterSizeTail <<
" " << FracClusterSizeTail <<
" MeanClusterSizeTail "
1509 << MeanClusterSizeTail);
1511 float FracClusterSize1plus2 = FracClusterSize1 + FracClusterSize2;
1512 float ITot = FracClusterSize1 + FracClusterSize2 + FracClusterSizeTail;
1514 if (FracClusterSize1plus2 != 0) {
1516 FracClusterSize2norm = FracClusterSize2 / FracClusterSize1plus2;
1519 float rndmCS = CLHEP::RandFlat::shoot(rndmEngine, ITot);
1521 if (stationName >= 2) {
1523 if (rndmCS < FracClusterSize1plus2) {
1525 if (xstripnorm <= FracClusterSize2norm / 2. * 1.3) {
1527 }
else if ((1.0 - FracClusterSize2norm / 2. * 1.3) <= xstripnorm) {
1533 float rndmCS1_2 = CLHEP::RandFlat::shoot(rndmEngine, 1);
1534 ClusterSize = 1 + (rndmCS1_2 < FracClusterSize2norm);
1537 }
else if ((FracClusterSize1plus2 <= rndmCS) && (rndmCS <= ITot)) {
1539 ClusterSize += int(CLHEP::RandExponential::shoot(rndmEngine, MeanClusterSizeTail));
1540 float rndmLR = CLHEP::RandFlat::shoot(rndmEngine, 1.0);
1541 if (rndmLR > 0.5) ClusterSize = -ClusterSize;
1547 if (rndmCS < FracClusterSize1) {
1549 }
else if (rndmCS < FracClusterSize1 + FracClusterSize2) {
1552 ClusterSize = int(CLHEP::RandExponential::shoot(rndmEngine, MeanClusterSizeTail));
1554 ClusterSize = std::max(ClusterSize, 1);
1555 if (ClusterSize > 1) {
1556 float rndmLR = CLHEP::RandFlat::shoot(rndmEngine, 1.0);
1557 if (rndmLR > 0.5) ClusterSize = -ClusterSize;
1565 double qcharge = 1.;
1566 const int particlePdgId = genParticle->pdg_id();
1568 qcharge = (
static_cast<double>((std::abs(particlePdgId) / 1000) % 100)) / (
static_cast<double>((std::abs(particlePdgId) / 10) % 100));
1569 qcharge = ((
static_cast<double>((
static_cast<int>(qcharge * 100))))) / 100;
1570 if (particlePdgId < 0.0) qcharge = -qcharge;
1572 const double QPx = genParticle->momentum().px();
1573 const double QPy = genParticle->momentum().py();
1574 const double QPz = genParticle->momentum().pz();
1575 const double QE = genParticle->momentum().e();
1576 const double QM2 = std::pow(QE, 2) - std::pow(QPx, 2) - std::pow(QPy, 2) - std::pow(QPz, 2);
1577 const double QP = std::hypot(QPx, QPy, QPz);
1578 const double QM = QM2 >=0 ? std::sqrt(QM2) : -1.;
1580 const double qbetagamma = QM > 0. ? QP / QM : -1.;
1584 for (
int i = 0; i < 12; i++) {
1585 if (Charge[i] == std::abs(qcharge)) {
1590 int i_v = -99, j_v = 99;
1591 if (qbetagamma != -1) {
1592 for (
int i = 0; i < 15; i++) {
1593 if (Velocity[i] <= qbetagamma) { i_v = i; }
1595 for (
int i = 14; i >= 0; i--) {
1596 if (Velocity[i] >= qbetagamma) { j_v = i; }
1601 double eff_fcp = 1.0, eff_muon = 1.0;
1602 if (i_e >= 0 && i_e <= 11) {
1603 if (validIndex(j_v, N_Velocity) && validIndex(i_v, N_Velocity) && (j_v - i_v) == 1) {
1604 const double delta_v = Velocity[i_v] - Velocity[j_v];
1605 eff_fcp = (Eff_garfield[i_e][i_v] - Eff_garfield[i_e][j_v]) / delta_v * qbetagamma +
1606 (Eff_garfield[i_e][j_v] * Velocity[i_v] - Eff_garfield[i_e][i_v] * Velocity[j_v]) / delta_v;
1607 eff_muon = (Eff_garfield[11][i_v] - Eff_garfield[11][j_v]) / delta_v * qbetagamma +
1608 (Eff_garfield[11][j_v] * Velocity[i_v] - Eff_garfield[11][i_v] * Velocity[j_v]) / delta_v;
1609 }
else if (i_v == 14 && j_v == 99) {
1610 eff_fcp = Eff_garfield[i_e][14];
1611 eff_muon = Eff_garfield[11][14];
1612 }
else if (i_v == -99 && j_v == 0) {
1613 eff_fcp = Eff_garfield[i_e][0];
1614 eff_muon = Eff_garfield[11][0];
1616 ATH_MSG_WARNING(
"Wrong particle with unknown velocity! Scale factor is set to be 1.");
1619 ATH_MSG_WARNING(
"Wrong particle with unknown charge! Scale factor is set to be 1.");
1622 const double eff_SF = eff_fcp / eff_muon;
1629 constexpr double tot_mean_narrow = 16.;
1630 constexpr double tot_sigma_narrow = 2.;
1631 constexpr double tot_mean_wide = 15.;
1632 constexpr double tot_sigma_wide = 4.5;
1636 if (CLHEP::RandFlat::shoot(rndmEngine)<0.75) {
1637 thetot = CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot_mean_narrow, tot_sigma_narrow);
1639 thetot = CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot_mean_wide, tot_sigma_wide);
1642 return (thetot > 0.) ? thetot : 0.;
float hitTime(const AFP_SIDSimHit &hit)
constexpr std::array< T, N > make_array(const T &def_val)
Helper function to initialize in-place arrays with non-zero values.
#define ATH_CHECK
Evaluate an expression and check for errors.
bool isValid() const
Test to see if the link can be dereferenced.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
ATLAS-specific HepMC functions.
Definition of the abstract IRDBAccessSvc interface.
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
Definition of the abstract IRDBRecord interface.
Definition of the abstract IRDBRecordset interface.
AtlasHitsVector< RPCSimHit > RPCSimHitCollection
struct TBPatternUnitContext Unknown
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 T * get(size_type n) const
Access an element, as an rvalue.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
a link optimized in size for a GenParticle in a McEventCollection
HepMC::ConstGenParticlePtr cptr() const
Dereference.
static HepMcParticleLink getRedirectedLink(const HepMcParticleLink &particleLink, uint32_t eventIndex, const EventContext &ctx)
Return a HepMcParticleLink pointing at the same particle, but in a different GenEvent.
virtual unsigned int size() const =0
This class saves the "context" of an expanded identifier (ExpandedIdentifier) for compact or hash ver...
size_type begin_index() const
size_type end_index() const
value_type get_compact() const
Get the compact id.
This is a "hash" representation of an Identifier.
Identifier32 get_identifier32() const
Get the 32-bit version Identifier, will be invalid if >32 bits needed.
virtual const Amg::Transform3D & transform() const override
Return local to global transform.
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
const RpcReadoutElement * getRpcReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
const Amg::Transform3D & absTransform() const
An RpcReadoutElement corresponds to a single RPC module; therefore typicaly a barrel muon station con...
bool rotatedRpcModule() const
int nGasGapPerLay() const
returns the number of gasgaps
int NphiStripPanels() const
returns the number of phi strip panels (1 or 2)
double distanceToEtaReadout(const Amg::Vector3D &P) const
virtual int stripNumber(const Amg::Vector2D &pos, const Identifier &id) const override final
strip number corresponding to local position.
Amg::Vector3D localGasGapPos(const Identifier &id) const
Returns the position of the gasGap w.r.t. rest frame of the chamber.
Amg::Vector3D stripPos(const Identifier &id) const
double distanceToPhiReadout(const Amg::Vector3D &P) const
Amg::Transform3D localToGlobalTransf(const Identifier &id) const
int Nstrips(bool measphi) const
returns the number of strips for the phi or eta plane
virtual int numberOfLayers(bool measphi=true) const override final
number of layers in phi/eta projection, same for eta/phi planes
double StripPitch(bool measphi) const
returns the strip pitch for the phi or eta plane
std::pair< HepMcParticleLink, MuonMCData > Deposit
std::optional< double > getFracClusterSize2(const Identifier &) const
std::optional< int > getProjectedTrack(const Identifier &) const
std::optional< double > getFracDeadStrip(const Identifier &) const
std::optional< double > getFracClusterSize1(const Identifier &) const
std::optional< double > getGapEfficiency(const Identifier &) const
std::optional< double > getEfficiency(const Identifier &) const
std::optional< double > getMeanClusterSize(const Identifier &) const
static const RpcHitIdHelper * GetHelper(unsigned int nGasGaps=2)
const_pointer_type cptr()
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
std::string store() const
Return the name of the store holding the object we are proxying.
const std::string & name() const
Return the StoreGate ID for the referenced object.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
pointer_type ptr()
Dereference the pointer.
TimedVector::const_iterator const_iterator
a smart pointer to a hit that also provides access to the extended timing info of the host event.
unsigned short eventId() const
the index of the component event in PileUpEventInfo.
Amg::Transform3D getTranslate3D(const double X, const double Y, const double Z)
: Returns a shift transformation along an arbitrary axis
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
Amg::Transform3D getRotateY3D(double angle)
Rotate the coordinate system by an angle around the z-axis.
HepMC3::ConstGenParticlePtr ConstGenParticlePtr
bool ignoreTruthLink(const T &p, bool vetoPileUp)
Helper function for SDO creation in PileUpTools.
bool isGenericMultichargedParticle(const T &p)
In addition, there is a need to identify ”Q-ball” and similar very exotic (multi-charged) particles w...
Ensure that the Athena extensions are properly loaded.
USAGE: openCoraCool.exe "COOLONL_SCT/COMP200".
std::list< value_t > type
type of the collection of timed data object
a struct encapsulating the identifier of a pile-up event
index_type index() const
the index of the component event in PileUpEventInfo
PileUpType type() const
the pileup type - minbias, cavern, beam halo, signal?
time_type time() const
bunch xing time in ns
#define THROW_EXCEPTION(MESSAGE)
Tell the compiler to optimize assuming that FP may trap.
#define CXXUTILS_TRAPPING_FP
int run(int argc, char *argv[])