18#include "GaudiKernel/SystemOfUnits.h"
19#include "GaudiKernel/PhysicalConstants.h"
21#include "GeoModelHelpers/TransformToStringConverter.h"
42#include "GeoModelKernel/throwExcept.h"
45#include "CLHEP/Random/RandExponential.h"
46#include "CLHEP/Random/RandFlat.h"
47#include "CLHEP/Random/RandGaussZiggurat.h"
63 constexpr int N_Charge = 12;
64 constexpr int N_Velocity = 15;
65 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};
66 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};
67 constexpr double Eff_garfield[N_Charge][N_Velocity] = {
68 {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},
69 {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},
70 {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},
71 {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},
72 {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},
73 {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},
74 {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},
75 {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},
76 {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},
77 {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},
78 {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},
79 {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}};
81 validIndex(
int idx,
int arraySize){
82 return (idx>=0) and (idx<arraySize);
88 constexpr double SIG_VEL = 4.8;
139 return StatusCode::FAILURE;
156 ATH_MSG_DEBUG(
"Ready to read parameters for cluster simulation from file");
174 return StatusCode::SUCCESS;
180 SmartIF<IGeoModelSvc> geoModel{Gaudi::svcLocator()->service(
"GeoModelSvc")};
183 return StatusCode::FAILURE;
187 std::string atlasVersion = geoModel->atlasVersion();
189 SmartIF<IRDBAccessSvc> rdbAccess{Gaudi::svcLocator()->service(
"RDBAccessSvc")};
192 return StatusCode::FAILURE;
198 std::string configVal =
"";
200 IRDBRecordset_ptr atlasCommonRec = rdbAccess->getRecordsetPtr(
"AtlasCommon", atlasVersion,
"ATLAS");
201 if (atlasCommonRec->
size() == 0) {
204 configVal = (*atlasCommonRec)[0]->getString(
"CONFIG");
205 ATH_MSG_INFO(
"From DD Database, Configuration is " << configVal);
206 if (configVal ==
"RUN1") {
208 }
else if (configVal ==
"RUN2") {
210 }
else if (configVal ==
"RUN3") {
212 }
else if (configVal ==
"RUN4") {
215 if (
run == DataPeriod::Unknown) {
216 ATH_MSG_FATAL(
"Unexpected value for geometry config read from the database: " << configVal);
217 return StatusCode::FAILURE;
224 ATH_MSG_INFO(
"From Geometry DB: MuonSpectrometer configuration is: RUN1 or MuonGeometry = R.06");
226 ATH_MSG_INFO(
"From Geometry DB: MuonSpectrometer configuration is: RUN2 or MuonGeometry = R.07");
227 else if (
run == Run3)
228 ATH_MSG_INFO(
"From Geometry DB: MuonSpectrometer configuration is: RUN3 or MuonGeometry = R.09");
229 else if (
run == Run4)
230 ATH_MSG_INFO(
"From Geometry DB: MuonSpectrometer configuration is: RUN4 or MuonGeometry = R.10");
243 if (configVal ==
"RUN1") {
262 ATH_MSG_INFO(
"Run3/4: configuration parameter not from COOL");
269 ATH_MSG_INFO(
"RPC Run1/2/3-dependent configuration is enforced");
271 ATH_MSG_WARNING(
"Run1/2/3-dependent configuration is bypassed; be careful with option settings");
282 return StatusCode::SUCCESS;
285template <
class CondType>
288 const CondType* & condPtr)
const {
291 ATH_MSG_DEBUG(
"No key has been configured for object "<<
typeid(CondType).name()<<
". Clear pointer");
293 return StatusCode::SUCCESS;
297 ATH_MSG_FATAL(
"Failed to load conditions object "<<key.fullKey()<<
".");
298 return StatusCode::FAILURE;
300 condPtr = readHandle.
cptr();
301 return StatusCode::SUCCESS;
310 m_thpcRPC = std::make_unique<TimedHitCollection<RPCSimHit>>();
313 return StatusCode::SUCCESS;
321 TimedHitCollList hitCollList;
324 hitCollList.empty()) {
326 return StatusCode::FAILURE;
331 TimedHitCollList::iterator iColl(hitCollList.begin());
332 TimedHitCollList::iterator endColl(hitCollList.end());
335 for (; iColl != endColl; ++iColl) {
339 ATH_MSG_DEBUG(
"RPCSimHitCollection found with " << hitCollPtr->
size() <<
" hits");
342 m_thpcRPC->insert(timeIndex, hitCollPtr);
346 return StatusCode::SUCCESS;
363 if (!hitCollection.
isValid()) {
364 ATH_MSG_ERROR(
"Could not get RPCSimHitCollection container " << hitCollection.
name() <<
" from store "
365 << hitCollection.
store());
366 return StatusCode::FAILURE;
370 m_thpcRPC = std::make_unique<TimedHitCollection<RPCSimHit>>(1);
372 ATH_MSG_DEBUG(
"RPCSimHitCollection found with " << hitCollection->size() <<
" hits");
374 return StatusCode::SUCCESS;
377 TimedHitCollList hitCollList;
381 return StatusCode::FAILURE;
383 if (hitCollList.empty()) {
385 return StatusCode::FAILURE;
391 m_thpcRPC = std::make_unique<TimedHitCollection<RPCSimHit>>();
393 TimedHitCollList::iterator iColl(hitCollList.begin());
394 TimedHitCollList::iterator endColl(hitCollList.end());
395 while (iColl != endColl) {
397 m_thpcRPC->insert(iColl->first, p_collection);
402 return StatusCode::SUCCESS;
407 StatusCode status = StatusCode::SUCCESS;
417 ATH_CHECK(sdoContainer.
record(std::make_unique<MuonSimDataCollection>()));
426 if (status.isFailure()) {
ATH_MSG_ERROR(
"doDigitization Failed"); }
427 for (
size_t coll_hash = 0; coll_hash < collections.size(); ++coll_hash) {
428 if (collections[coll_hash]) {
429 ATH_CHECK( digitContainer->addCollection (collections[coll_hash].release(), coll_hash) );
441 StatusCode status = StatusCode::SUCCESS;
454 ATH_CHECK(sdoContainer.
record(std::make_unique<MuonSimDataCollection>()));
463 if (StatusCode::FAILURE == status) {
471 for (
size_t coll_hash = 0; coll_hash < collections.size(); ++coll_hash) {
472 if (collections[coll_hash]) {
473 ATH_CHECK( digitContainer->addCollection (collections[coll_hash].release(), coll_hash) );
485 rngWrapper->
setSeed(name(), ctx);
486 CLHEP::HepRandomEngine* rndmEngine = rngWrapper->
getEngine(ctx);
492 std::unique_ptr<RPCSimHitCollection> inputSimHitColl{std::make_unique<RPCSimHitCollection>(
"RPC_Hits")};
502 return StatusCode::FAILURE;
505 struct SimDataContent {
507 std::vector<MuonSimData::Deposit> deposits;
512 while (
m_thpcRPC->nextDetectorElement(i, e)) {
515 std::map<Identifier, SimDataContent> channelSimDataMap;
526 const int idHit = hit.
RPCid();
528 const double globalHitTime{
hitTime(phit)};
532 const double bunchTime{globalHitTime - hit.
globalTime()};
534 ATH_MSG_DEBUG(
"Global time " << globalHitTime <<
" G4 time " << G4Time <<
" Bunch time " << bunchTime);
537 ATH_MSG_VERBOSE(
"Validation: globalHitTime, G4Time, BCtime = " << globalHitTime <<
" " << G4Time <<
" " << bunchTime);
538 inputSimHitColl->Emplace(idHit, globalHitTime, hit.
localPosition(),
545 const std::string stationName =
m_muonHelper->GetStationName(idHit);
547 const int stationPhi =
m_muonHelper->GetPhiSector(idHit);
550 const int doubletPhi =
m_muonHelper->GetDoubletPhi(idHit);
559 ATH_MSG_WARNING(
"Failed to construct the element ID from "<<stationName
560 <<
", stationEta: "<<stationEta<<
", stationPhi: "<<stationPhi<<
", doubletR: "<<doubletR);
565 <<
" stationName " << stationName <<
" stationEta " << stationEta <<
" stationPhi " << stationPhi <<
" doubletR "
566 << doubletR <<
" doubletZ " << doubletZ <<
" doubletPhi " << doubletPhi <<
" gasGap " << gasGap);
574 gasGap = gasGap == 1 ? 2 : 1;
578 bool isValidEta{
false}, isValidPhi{
false};
579 const Identifier idpaneleta =
m_idHelper->channelID(elementID, doubletZ, doubletPhi, gasGap, 0, 1, isValidEta);
580 const Identifier idpanelphi =
m_idHelper->channelID(elementID, doubletZ, doubletPhi, gasGap, 1, 1, isValidPhi);
581 if (!isValidEta || !isValidPhi) {
583 <<
" stationName " << stationName <<
" stationEta " << stationEta <<
" stationPhi " << stationPhi
584 <<
" doubletR " << doubletR <<
" doubletZ " << doubletZ <<
" doubletPhi " << doubletPhi <<
" gasGap "
593 const double corrtimejitter = tmp_CorrJitter > 0.01 ?
594 CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0., tmp_CorrJitter) : 0.;
604 std::array<int, 3> pcseta =
physicalClusterSize(ctx, reEle, idpaneleta, gapCentre, rndmEngine);
605 ATH_MSG_VERBOSE(
"Simulated cluster on eta panel: size/first/last= " << pcseta[0] <<
"/" << pcseta[1] <<
"/" << pcseta[2]);
606 std::array<int, 3> pcsphi =
physicalClusterSize(ctx, reEle, idpanelphi, gapCentre, rndmEngine);
607 ATH_MSG_VERBOSE(
"Simulated cluster on phi panel: size/first/last= " << pcsphi[0] <<
"/" << pcsphi[1] <<
"/" << pcsphi[2]);
612 const Identifier atlasRpcIdeta =
m_idHelper->channelID(elementID, doubletZ, doubletPhi, gasGap, 0, pcseta[1], isValidEta);
613 const Identifier atlasRpcIdphi =
m_idHelper->channelID(elementID, doubletZ, doubletPhi, gasGap, 1, pcsphi[1], isValidPhi);
616 const auto [etaStripOn, phiStripOn] =
detectionEfficiency(ctx, idpaneleta, idpanelphi, rndmEngine, particleLink);
617 ATH_MSG_DEBUG(
"SetPhiOn " << phiStripOn <<
" SetEtaOn " << etaStripOn);
619 for (
bool imeasphi : {
false,
true}) {
620 if (!imeasphi && (!etaStripOn || !isValidEta))
continue;
621 if (imeasphi && (!phiStripOn || !isValidPhi))
continue;
625 const Identifier& atlasId = !imeasphi ? atlasRpcIdeta : atlasRpcIdphi;
626 std::array<int, 3> pcs{!imeasphi ? pcseta : pcsphi};
628 ATH_MSG_DEBUG(
"SetOn: stationName " << stationName <<
" stationEta " << stationEta <<
" stationPhi " << stationPhi
629 <<
" doubletR " << doubletR <<
" doubletZ " << doubletZ <<
" doubletPhi " << doubletPhi
630 <<
" gasGap " << gasGap <<
" measphi " << imeasphi);
638 ATH_MSG_DEBUG(
"Simulated cluster1: size/first/last= " << pcs[0] <<
"/" << pcs[1] <<
"/" << pcs[2]);
645 <<
" hit "<<
m_idHelper->print_to_string(atlasId)
657 double tns = G4Time + proptime + corrtimejitter;
658 ATH_MSG_VERBOSE(
"TOF+propagation time " << tns <<
" /s where proptime " << proptime <<
"/s");
660 double time = tns + bunchTime;
664 long long int packedMCword =
PackMCTruth(proptime, bunchTime, pos.y(), pos.z());
666 double* b =
reinterpret_cast<double*
>(&packedMCword);
678 if (channelSimDataMap.find(atlasId) == channelSimDataMap.end()) {
679 SimDataContent& content = channelSimDataMap[atlasId];
680 content.channelId = atlasId;
681 content.deposits.push_back(deposit);
682 content.gpos = reEle->
transform(atlasId)*
684 content.simTime =
hitTime(phit);
685 ATH_MSG_VERBOSE(
"adding SDO entry: r " << content.gpos.perp() <<
" z " << content.gpos.z());
697 for (
int clus = pcs[1]; clus <= pcs[2]; ++clus) {
698 Identifier newId =
m_idHelper->channelID(stationName, stationEta, stationPhi, doubletR, doubletZ,
699 doubletPhi, gasGap, imeasphi, clus,
isValid);
701 ATH_MSG_WARNING(__FILE__<<
":"<<__LINE__<<
"Channel "<< stationName<<
" "<<stationEta<<
" "<<stationPhi<<
" "<< doubletR<<
" "<<doubletZ
702 <<
" "<< doubletPhi<<
" "<< gasGap <<
" "<< imeasphi<<
" "<< clus<<
" is invalid");
707 if (stationName.find(
"BI") != std::string::npos) {
708 ATH_MSG_WARNING(
"Temporary skipping creation of RPC digit for stationName="
709 << stationName <<
", eta=" << stationEta <<
", phi=" << stationPhi <<
", doubletR=" << doubletR
710 <<
", doubletZ=" << doubletZ <<
", doubletPhi=" << doubletPhi <<
", gasGap=" << gasGap
711 <<
", measuresPhi=" << imeasphi <<
", strip=" << clus <<
", cf. ATLASRECTS-6124");
712 return StatusCode::SUCCESS;
716 return StatusCode::FAILURE;
725 std::vector<MuonSimData::Deposit> newdeps;
726 newdeps.push_back(deposit);
736 for (
auto it = channelSimDataMap.begin(); it != channelSimDataMap.end(); ++it) {
738 simData.setPosition(it->second.gpos);
739 simData.setTime(it->second.simTime);
740 auto insertResult = sdoContainer->insert(std::make_pair(it->first,
simData));
741 if (!insertResult.second)
742 ATH_MSG_WARNING(
"Attention: this sdo is not recorded, since the identifier already exists in the sdoContainer map");
758 const std::vector<MuonSimData::Deposit> theDeps = (*map_iter).second;
762 std::multimap<double, MuonSimData::Deposit> times;
765 for (
unsigned int k = 0; k < theDeps.size(); k++) {
766 double time = theDeps[k].second.secondEntry();
767 times.insert(std::multimap<double, MuonSimData::Deposit>::value_type(time, theDeps[k]));
774 std::multimap<double, MuonSimData::Deposit>::iterator map_dep_iter = times.begin();
777 double last_time = -10000;
778 for (; map_dep_iter != times.end(); ++map_dep_iter) {
779 double currTime = (*map_dep_iter).first;
785 if (sdoContainer->find(theId) != sdoContainer->end())
787 std::map<Identifier, MuonSimData>::const_iterator it = sdoContainer->find(theId);
788 std::vector<MuonSimData::Deposit> deps = ((*it).second).getdeposits();
789 deps.push_back((*map_dep_iter).second);
792 std::vector<MuonSimData::Deposit> deposits;
793 deposits.push_back((*map_dep_iter).second);
794 std::pair<std::map<Identifier, MuonSimData>::iterator,
bool> insertResult =
795 sdoContainer->insert(std::make_pair(theId,
MuonSimData(deposits, 0)));
796 if (!insertResult.second)
798 "Attention TEMP: this sdo is not recorded, since the identifier already exists in the sdoContainer map");
802 if (std::abs(currTime - last_time) > (
m_deadTime)) {
803 ATH_MSG_DEBUG(
"deposit with time " << currTime <<
" is distant enough from previous (if any) hit on teh same strip");
804 last_time = (*map_dep_iter).first;
807 double uncorrjitter = 0;
810 if (tmp_UncorrJitter > 0.01) uncorrjitter = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0., tmp_UncorrJitter);
820 double newDigit_time = currTime + uncorrjitter +
m_rpc_time_shift - tp - propTimeFromStripCenter;
822 double digi_ToT = -1.;
825 ATH_MSG_VERBOSE(
"last_time=currTime " << last_time <<
" jitter " << uncorrjitter <<
" TOFcorrection " << tp <<
" shift "
829 bool outsideDigitizationWindow =
outsideWindow(newDigit_time);
830 if (outsideDigitizationWindow) {
831 ATH_MSG_VERBOSE(
"hit outside digitization window - do not produce digits");
840 last_time = (*map_dep_iter).first;
842 std::unique_ptr<RpcDigit> newDigit = std::make_unique<RpcDigit>(theId, newDigit_time, digi_ToT,
false);
848 if (
m_idHelper->get_hash(elemId, coll_hash, &rpcContext)) {
849 ATH_MSG_ERROR(
"Unable to get RPC hash id from RPC Digit collection "
850 <<
"context begin_index = " << rpcContext.
begin_index()
851 <<
" context end_index = " << rpcContext.
end_index() <<
" the identifier is ");
859 if (coll_hash >= collections.size()) {
860 collections.resize (coll_hash+1);
862 digitCollection = collections[coll_hash].
get();
863 if (!digitCollection) {
864 collections[coll_hash] = std::make_unique<RpcDigitCollection>(elemId, coll_hash);
865 digitCollection = collections[coll_hash].
get();
867 digitCollection->
push_back(std::move(newDigit));
871 if (sdoContainer->find(theId) != sdoContainer->end()) {
872 std::map<Identifier, MuonSimData>::const_iterator it = sdoContainer->find(theId);
873 std::vector<MuonSimData::Deposit> deps = ((*it).second).getdeposits();
874 deps.push_back((*map_dep_iter).second);
876 std::vector<MuonSimData::Deposit> deposits;
877 deposits.push_back((*map_dep_iter).second);
878 std::pair<std::map<Identifier, MuonSimData>::iterator,
bool> insertResult =
879 sdoContainer->insert(std::make_pair(theId,
MuonSimData(deposits, 0)));
880 if (!insertResult.second)
882 "Attention: this sdo is not recorded, since teh identifier already exists in the sdoContainer map");
887 ATH_MSG_DEBUG(
"discarding digit due to dead time: " << (*map_dep_iter).first <<
" " << last_time);
899 return StatusCode::SUCCESS;
916 (flip ?
Amg::getRotateY3D(180.*Gaudi::Units::deg) : Amg::Transform3D::Identity())};
927 CLHEP::HepRandomEngine* rndmEngine)
const {
930 std::array<int, 3>
result{};
934 const int doubletPhi =
m_idHelper->doubletPhi(
id);
936 const bool measuresPhi =
m_idHelper->measuresPhi(
id);
937 const double pitch= ele->
StripPitch(measuresPhi);
940 const int nstrip = ele->
stripNumber(position.block<2,1>(0,0),
id);
941 const int numStrips = ele->
Nstrips(measuresPhi);
946 if (nstrip < 1 || nstrip > numStrips) {
950 float xstripnorm = (locStripPos -position).
x() / pitch ;
963 std::array<int, 3>&& pcs,
971 }
else if (pcs[0] == 2) {
973 }
else if (pcs[0] > 2) {
974 pcs[1] = pcs[1] - pcs[0] / 2;
975 if (fmod(pcs[0], 2) == 0) pcs[1] = pcs[1] + 1;
976 pcs[2] = pcs[1] + pcs[0] - 1;
977 }
else if (pcs[0] < -2) {
978 pcs[1] = pcs[1] + pcs[0] / 2;
979 pcs[2] = pcs[1] - pcs[0] - 1;
984 pcs[1] = std::clamp(pcs[1], 1, nstrips);
985 pcs[2] = std::clamp(pcs[2], 1, nstrips);
987 pcs[0] = pcs[2] - pcs[1] + 1;
1005 return std::abs(distance * SIG_VEL * 1.e-3);
1012 ATH_MSG_WARNING(
"A poblem: packing a propagation time <0 " << proptime <<
" redefine it as 0");
1015 long long int new_proptime = int(proptime * 10) & 0xff;
1021 long long int new_bctime = int((bctime + 300.) * 10.) & 0xffff;
1026 long long int new_posy = int((posy + 1500.) * 10.) & 0xffff;
1031 long long int new_posz = int((posz + 1500.) * 10.) & 0xffff;
1033 return (new_proptime + (new_bctime << 8) + (new_posy << 24) + (new_posz << 40));
1039 using Repacker =
union
1047 MCTruth.dWord = theWord;
1048 proptime = ((MCTruth.iWord) & 0x00000000000000ffLL) / 10.;
1049 bctime = (((MCTruth.iWord) & 0x0000000000ffff00LL) >> 8) / 10.;
1050 posy = (((MCTruth.iWord) & 0x000000ffff000000LL) >> 24) / 10.;
1051 posz = (((MCTruth.iWord) & 0x00ffff0000000000LL) >> 40) / 10.;
1054 bctime = bctime - 300.;
1055 posy = posy - 1500.;
1056 posz = posz - 1500.;
1062 SmartIF<ITagInfoMgr> tagInfoMgr{Gaudi::svcLocator()->service(
"TagInfoMgr")};
1063 if (!tagInfoMgr) {
return StatusCode::FAILURE; }
1065 std::string RpctimeSchema =
"";
1066 std::stringstream RpctimeShift;
1070 RpctimeSchema =
"Datalike_TOFoff_TimeShift" + RpctimeShift.str() +
"nsec";
1072 RpctimeSchema =
"G4like_TOFon_TimeShift" + RpctimeShift.str() +
"nsec";
1077 if (
sc.isFailure()) {
1084 return StatusCode::SUCCESS;
1092 CLHEP::HepRandomEngine* rndmEngine,
1097 ATH_MSG_DEBUG(
"RpcDigitizationTool::in DetectionEfficiency");
1105 float maxGeomEff{0.99}, PhiAndEtaEff{0.99}, OnlyEtaEff{0.f}, OnlyPhiEff{0.f};
1108 int stationName =
m_idHelper->stationName(IdEta);
1109 int stationEta =
m_idHelper->stationEta(IdEta);
1114 return std::make_pair(
false,
false);
1119 return std::make_pair(
true,
true);
1121 bool etaStripOn{
true}, phiStripOn{
true};
1126 unsigned int index = stationName - 2;
1128 if (stationName > 5 && stationName < 50)
index =
index - 2;
1130 else if (stationName > 50)
1136 THROW_EXCEPTION(
"Index out of array in Detection Efficiency SideA " <<
index <<
" stationName = " << stationName);
1143 if (stationEta < 0) {
1145 THROW_EXCEPTION(
"Index out of array in Detection Efficiency SideC " <<
index <<
" stationName = " << stationName);
1162 ATH_MSG_DEBUG(
"Efficiencies and cluster size + dead strips will be extracted from COOL");
1164 double FracDeadStripEta{0.}, FracDeadStripPhi{0.};
1165 double EtaPanelEfficiency{1.}, PhiPanelEfficiency{1.}, GapEfficiency{1.};
1166 int RPC_ProjectedTracksEta = 0;
1168 std::optional<double> fracDeadStripEtaFromCOOL = readCdo->
getFracDeadStrip(IdEta);
1169 std::optional<double> fracDeadStripPhiFromCOOL = readCdo->
getFracDeadStrip(IdPhi);
1171 bool noEntryInDb = !fracDeadStripEtaFromCOOL || !fracDeadStripPhiFromCOOL;
1173 FracDeadStripEta = fracDeadStripEtaFromCOOL.value_or(0.);
1174 FracDeadStripPhi = fracDeadStripPhiFromCOOL.value_or(0.);
1177 EtaPanelEfficiency = readCdo->
getEfficiency(IdEta).value_or(1.);
1178 PhiPanelEfficiency = readCdo->
getEfficiency(IdPhi).value_or(1.);
1181 if (std::abs(FracDeadStripEta - 1.) < 0.001) {
1182 ATH_MSG_DEBUG(
"Watch out: SPECIAL CASE: Read from Cool: FracDeadStripEta/Phi "
1183 << FracDeadStripEta <<
"/" << FracDeadStripPhi <<
" RPC_ProjectedTracksEta " << RPC_ProjectedTracksEta
1184 <<
" Eta/PhiPanelEfficiency " << EtaPanelEfficiency <<
"/" << PhiPanelEfficiency <<
" gapEff " << GapEfficiency
1188 FracDeadStripPhi = 0.;
1189 ATH_MSG_VERBOSE(
"Watch out: SPECIAL CASE: Resetting FracDeadStripPhi " << FracDeadStripPhi <<
" ignoring phi dead strips ");
1197 bool changing =
false;
1198 ATH_MSG_DEBUG(
"Read from Cool: FracDeadStripEta/Phi " << FracDeadStripEta <<
"/" << FracDeadStripPhi <<
" RPC_ProjectedTracksEta "
1199 << RPC_ProjectedTracksEta <<
" Eta/PhiPanelEfficiency " << EtaPanelEfficiency
1200 <<
"/" << PhiPanelEfficiency <<
" gapEff " << GapEfficiency);
1202 if ((maxGeomEff - FracDeadStripEta) - EtaPanelEfficiency < -0.011) {
1203 ATH_MSG_DEBUG(
"Ineff. from dead strips on Eta Panel larger that measured efficiency: deadFrac="
1204 << FracDeadStripEta <<
" Panel Eff=" << EtaPanelEfficiency <<
" for Panel " <<
m_idHelper->show_to_string(IdEta));
1205 ATH_MSG_DEBUG(
"... see the corresponding report from RpcDetectorStatusDbTool");
1207 EtaPanelEfficiency = maxGeomEff - FracDeadStripEta;
1211 if ((maxGeomEff - FracDeadStripPhi) - PhiPanelEfficiency < -0.011) {
1212 ATH_MSG_DEBUG(
"Ineff. from dead strips on Phi Panel larger that measured efficiency: deadFrac="
1213 << FracDeadStripPhi <<
" Panel Eff=" << PhiPanelEfficiency <<
" for Panel " <<
m_idHelper->show_to_string(IdPhi));
1214 ATH_MSG_DEBUG(
"... see the corresponding report among the warnings of RpcDetectorStatusDbTool");
1216 PhiPanelEfficiency = maxGeomEff - FracDeadStripPhi;
1220 if ((maxGeomEff - FracDeadStripEta * FracDeadStripPhi) - GapEfficiency < -0.011) {
1221 ATH_MSG_DEBUG(
"Ineff. from dead strips on Eta/Phi Panels larger that measured EtaORPhi efficiency: deadFrac="
1222 << FracDeadStripEta * FracDeadStripPhi <<
" EtaORPhi Eff=" << GapEfficiency <<
" for GasGap "
1224 ATH_MSG_DEBUG(
"... see the corresponding report among the warnings of RpcDetectorStatusDbTool");
1226 GapEfficiency = maxGeomEff - FracDeadStripEta * FracDeadStripPhi;
1230 ATH_MSG_DEBUG(
"Rinormalized Values from Cool: FracDeadStripEta/Phi "
1231 << FracDeadStripEta <<
"/" << FracDeadStripPhi <<
" RPC_ProjectedTracksEta " << RPC_ProjectedTracksEta
1232 <<
" Eta/PhiPanelEfficiency " << EtaPanelEfficiency <<
"/" << PhiPanelEfficiency <<
" gapEff " << GapEfficiency);
1236 if ((FracDeadStripEta > 0.0 && FracDeadStripEta < 1.0) || (FracDeadStripPhi > 0.0 && FracDeadStripPhi < 1.0) || (noEntryInDb)) {
1237 EtaPanelEfficiency = EtaPanelEfficiency / (maxGeomEff - FracDeadStripEta);
1238 PhiPanelEfficiency = PhiPanelEfficiency / (maxGeomEff - FracDeadStripPhi);
1239 GapEfficiency = GapEfficiency / (maxGeomEff - FracDeadStripEta * FracDeadStripPhi);
1241 if (EtaPanelEfficiency > maxGeomEff) EtaPanelEfficiency = maxGeomEff;
1242 if (PhiPanelEfficiency > maxGeomEff) PhiPanelEfficiency = maxGeomEff;
1243 if (GapEfficiency > maxGeomEff) GapEfficiency = maxGeomEff;
1245 if (EtaPanelEfficiency > GapEfficiency) GapEfficiency = EtaPanelEfficiency;
1246 if (PhiPanelEfficiency > GapEfficiency) GapEfficiency = PhiPanelEfficiency;
1247 ATH_MSG_DEBUG(
"Eff Redefined (to correct for deadfrac): FracDeadStripEta/Phi "
1248 <<
" Eta/PhiPanelEfficiency " << EtaPanelEfficiency <<
"/" << PhiPanelEfficiency <<
" gapEff "
1254 PhiAndEtaEff = float(EtaPanelEfficiency + PhiPanelEfficiency - GapEfficiency);
1255 if (PhiAndEtaEff < 0.) PhiAndEtaEff = 0.;
1256 OnlyEtaEff = float(EtaPanelEfficiency - PhiAndEtaEff);
1257 if (OnlyEtaEff < 0.) OnlyEtaEff = 0.;
1258 OnlyPhiEff = float(PhiPanelEfficiency - PhiAndEtaEff);
1259 if (OnlyPhiEff < 0.) OnlyPhiEff = 0.;
1263 bool applySpecialPatch =
false;
1269 applySpecialPatch =
true;
1271 "Applying special patch for BMS at |eta|=6 lowPt plane -dbbZ=2 and dbPhi=1 ... will use default eff. for Id "
1274 "Applying special patch: THIS HAS TO BE DONE IF /RPC/DQMF/ELEMENT_STATUS tag is "
1275 "RPCDQMFElementStatus_2012_Jaunuary_2");
1281 if (applySpecialPatch || RPC_ProjectedTracksEta < m_CutProjectedTracks || RPC_ProjectedTracksEta > 10000000 ||
1282 EtaPanelEfficiency > 1 || EtaPanelEfficiency < 0 || PhiPanelEfficiency > 1 || PhiPanelEfficiency < 0 || GapEfficiency > 1 ||
1283 GapEfficiency < 0) {
1285 THROW_EXCEPTION(
"Index out of array in Detection Efficiency SideA COOLDB" <<
index <<
" stationName = " << stationName);
1289 <<
" resetting eff. from cool with default(python) values ");
1295 if (stationEta < 0) {
1297 THROW_EXCEPTION(
"Index out of array in Detection Efficiency SideC COOLDB" <<
index <<
" stationName = " << stationName);
1306 float effgap = PhiAndEtaEff + OnlyEtaEff + OnlyPhiEff;
1307 float s_EtaPanelEfficiency = 1. - FracDeadStripEta;
1308 float s_PhiPanelEfficiency = 1. - FracDeadStripPhi;
1309 float s_PhiAndEtaEff = s_EtaPanelEfficiency * s_PhiPanelEfficiency / effgap;
1310 if (s_PhiAndEtaEff < PhiAndEtaEff) PhiAndEtaEff = s_PhiAndEtaEff;
1311 float s_OnlyEtaEff = s_EtaPanelEfficiency - PhiAndEtaEff;
1312 float s_OnlyPhiEff = s_PhiPanelEfficiency - PhiAndEtaEff;
1314 if (s_OnlyEtaEff < OnlyEtaEff) OnlyEtaEff = s_OnlyEtaEff;
1315 if (s_OnlyPhiEff < OnlyPhiEff) OnlyPhiEff = s_OnlyPhiEff;
1319 float VolEff = PhiAndEtaEff + OnlyEtaEff + OnlyPhiEff;
1320 if (VolEff > maxGeomEff) {
1321 PhiAndEtaEff = (PhiAndEtaEff / VolEff) * maxGeomEff;
1322 OnlyEtaEff = (OnlyEtaEff / VolEff) * maxGeomEff;
1323 OnlyPhiEff = (OnlyPhiEff / VolEff) * maxGeomEff;
1336 PhiAndEtaEff = PhiAndEtaEff * eff_sf;
1337 OnlyEtaEff = OnlyEtaEff * eff_sf;
1338 OnlyPhiEff = OnlyPhiEff * eff_sf;
1342 float I0 = PhiAndEtaEff;
1343 float I1 = PhiAndEtaEff + OnlyEtaEff;
1344 float ITot = PhiAndEtaEff + OnlyEtaEff + OnlyPhiEff;
1346 float GapEff = ITot ;
1347 float PhiEff = PhiAndEtaEff + OnlyPhiEff;
1348 float EtaEff = PhiAndEtaEff + OnlyEtaEff;
1350 ATH_MSG_DEBUG(
"DetectionEfficiency: Final Efficiency Values applied for "
1351 <<
m_idHelper->show_to_string(IdEta) <<
" are " << PhiAndEtaEff <<
"=PhiAndEtaEff " << OnlyEtaEff
1352 <<
"=OnlyEtaEff " << OnlyPhiEff <<
"=OnlyPhiEff " << GapEff <<
"=GapEff " << EtaEff <<
"=EtaEff " << PhiEff
1355 float rndmEff = CLHEP::RandFlat::shoot(rndmEngine, 1);
1360 }
else if ((I0 <= rndmEff) && (rndmEff < I1)) {
1363 }
else if ((I1 <= rndmEff) && (rndmEff <= ITot)) {
1371 return std::make_pair(etaStripOn, phiStripOn);
1378 CLHEP::HepRandomEngine* rndmEngine)
const {
1379 ATH_MSG_DEBUG(
"RpcDigitizationTool::in determineClusterSize");
1383 int ClusterSize = 1;
1385 double FracClusterSize1{1.}, FracClusterSize2{0.}, MeanClusterSize{1.},
1386 FracClusterSizeTail{0.}, MeanClusterSizeTail{1.},
1387 FracClusterSize2norm{0.};
1390 int stationName =
m_idHelper->stationName(idRpcStrip);
1391 int stationEta =
m_idHelper->stationEta(idRpcStrip);
1392 int measuresPhi =
m_idHelper->measuresPhi(idRpcStrip);
1394 unsigned int index = stationName - 2;
1396 if (stationName > 5 && stationName < 50)
index =
index - 2;
1398 else if (stationName > 50)
1408 ATH_MSG_ERROR(
"Index out of array in determineClusterSize SideA " <<
index <<
" statName " << stationName);
1416 if (stationEta < 0) {
1422 ATH_MSG_ERROR(
"Index out of array in determineClusterSize SideC " <<
index <<
" statName " << stationName);
1447 ATH_MSG_DEBUG(
"FracClusterSize1 and 2 " << FracClusterSize1 <<
" " << FracClusterSize2);
1449 FracClusterSizeTail = 1. - FracClusterSize1 - FracClusterSize2;
1451 MeanClusterSizeTail = MeanClusterSize - FracClusterSize1 - 2 * FracClusterSize2;
1453 ATH_MSG_DEBUG(
"MeanClusterSizeTail and FracClusterSizeTail " << MeanClusterSizeTail <<
" " << FracClusterSizeTail);
1456 if (RPC_ProjectedTracks < m_CutProjectedTracks || RPC_ProjectedTracks > 10000000 || MeanClusterSize >
m_CutMaxClusterSize ||
1457 MeanClusterSize <= 1 || FracClusterSizeTail < 0 || FracClusterSize1 < 0 || FracClusterSize2 < 0 || FracClusterSizeTail > 1 ||
1458 FracClusterSize1 > 1 || FracClusterSize2 > 1) {
1459 if (stationName >= 2) {
1465 ATH_MSG_ERROR(
"Index out of array in determineClusterSize SideA " <<
index <<
" statName " << stationName);
1473 if (stationEta < 0) {
1477 ATH_MSG_ERROR(
"Index out of array in determineClusterSize SideC " <<
index <<
" statName " << stationName);
1494 FracClusterSize1 = std::min(FracClusterSize1, 1.);
1495 FracClusterSize2 = std::min(FracClusterSize2, 1.);
1496 FracClusterSizeTail = std::min(FracClusterSizeTail, 1.);
1497 float FracTot = FracClusterSize1 + FracClusterSize2 + FracClusterSizeTail;
1498 if (FracTot != 1. && FracTot > 0) {
1499 FracClusterSize1 = FracClusterSize1 / FracTot;
1500 FracClusterSize2 = FracClusterSize2 / FracTot;
1501 FracClusterSizeTail = FracClusterSizeTail / FracTot;
1503 if (MeanClusterSizeTail < 0 || MeanClusterSizeTail > 10) MeanClusterSizeTail = 1;
1505 ATH_MSG_VERBOSE(
"ClusterSize Final " << FracClusterSize1 <<
" FracClusterSize1 " << FracClusterSize2 <<
" FracClusterSize2 "
1506 << FracClusterSizeTail <<
" " << FracClusterSizeTail <<
" MeanClusterSizeTail "
1507 << MeanClusterSizeTail);
1509 float FracClusterSize1plus2 = FracClusterSize1 + FracClusterSize2;
1510 float ITot = FracClusterSize1 + FracClusterSize2 + FracClusterSizeTail;
1512 if (FracClusterSize1plus2 != 0) {
1514 FracClusterSize2norm = FracClusterSize2 / FracClusterSize1plus2;
1517 float rndmCS = CLHEP::RandFlat::shoot(rndmEngine, ITot);
1519 if (stationName >= 2) {
1521 if (rndmCS < FracClusterSize1plus2) {
1523 if (xstripnorm <= FracClusterSize2norm / 2. * 1.3) {
1525 }
else if ((1.0 - FracClusterSize2norm / 2. * 1.3) <= xstripnorm) {
1531 float rndmCS1_2 = CLHEP::RandFlat::shoot(rndmEngine, 1);
1532 ClusterSize = 1 + (rndmCS1_2 < FracClusterSize2norm);
1535 }
else if ((FracClusterSize1plus2 <= rndmCS) && (rndmCS <= ITot)) {
1537 ClusterSize += int(CLHEP::RandExponential::shoot(rndmEngine, MeanClusterSizeTail));
1538 float rndmLR = CLHEP::RandFlat::shoot(rndmEngine, 1.0);
1539 if (rndmLR > 0.5) ClusterSize = -ClusterSize;
1545 if (rndmCS < FracClusterSize1) {
1547 }
else if (rndmCS < FracClusterSize1 + FracClusterSize2) {
1550 ClusterSize = int(CLHEP::RandExponential::shoot(rndmEngine, MeanClusterSizeTail));
1552 ClusterSize = std::max(ClusterSize, 1);
1553 if (ClusterSize > 1) {
1554 float rndmLR = CLHEP::RandFlat::shoot(rndmEngine, 1.0);
1555 if (rndmLR > 0.5) ClusterSize = -ClusterSize;
1563 double qcharge = 1.;
1564 const int particlePdgId = genParticle->pdg_id();
1566 qcharge = (
static_cast<double>((std::abs(particlePdgId) / 1000) % 100)) / (
static_cast<double>((std::abs(particlePdgId) / 10) % 100));
1567 qcharge = ((
static_cast<double>((
static_cast<int>(qcharge * 100))))) / 100;
1568 if (particlePdgId < 0.0) qcharge = -qcharge;
1570 const double QPx = genParticle->momentum().px();
1571 const double QPy = genParticle->momentum().py();
1572 const double QPz = genParticle->momentum().pz();
1573 const double QE = genParticle->momentum().e();
1574 const double QM2 = std::pow(QE, 2) - std::pow(QPx, 2) - std::pow(QPy, 2) - std::pow(QPz, 2);
1575 const double QP = std::hypot(QPx, QPy, QPz);
1576 const double QM = QM2 >=0 ? std::sqrt(QM2) : -1.;
1578 const double qbetagamma = QM > 0. ? QP / QM : -1.;
1582 for (
int i = 0; i < 12; i++) {
1583 if (Charge[i] == std::abs(qcharge)) {
1588 int i_v = -99, j_v = 99;
1589 if (qbetagamma != -1) {
1590 for (
int i = 0; i < 15; i++) {
1591 if (Velocity[i] <= qbetagamma) { i_v = i; }
1593 for (
int i = 14; i >= 0; i--) {
1594 if (Velocity[i] >= qbetagamma) { j_v = i; }
1599 double eff_fcp = 1.0, eff_muon = 1.0;
1600 if (i_e >= 0 && i_e <= 11) {
1601 if (validIndex(j_v, N_Velocity) && validIndex(i_v, N_Velocity) && (j_v - i_v) == 1) {
1602 const double delta_v = Velocity[i_v] - Velocity[j_v];
1603 eff_fcp = (Eff_garfield[i_e][i_v] - Eff_garfield[i_e][j_v]) / delta_v * qbetagamma +
1604 (Eff_garfield[i_e][j_v] * Velocity[i_v] - Eff_garfield[i_e][i_v] * Velocity[j_v]) / delta_v;
1605 eff_muon = (Eff_garfield[11][i_v] - Eff_garfield[11][j_v]) / delta_v * qbetagamma +
1606 (Eff_garfield[11][j_v] * Velocity[i_v] - Eff_garfield[11][i_v] * Velocity[j_v]) / delta_v;
1607 }
else if (i_v == 14 && j_v == 99) {
1608 eff_fcp = Eff_garfield[i_e][14];
1609 eff_muon = Eff_garfield[11][14];
1610 }
else if (i_v == -99 && j_v == 0) {
1611 eff_fcp = Eff_garfield[i_e][0];
1612 eff_muon = Eff_garfield[11][0];
1614 ATH_MSG_WARNING(
"Wrong particle with unknown velocity! Scale factor is set to be 1.");
1617 ATH_MSG_WARNING(
"Wrong particle with unknown charge! Scale factor is set to be 1.");
1620 const double eff_SF = eff_fcp / eff_muon;
1627 constexpr double tot_mean_narrow = 16.;
1628 constexpr double tot_sigma_narrow = 2.;
1629 constexpr double tot_mean_wide = 15.;
1630 constexpr double tot_sigma_wide = 4.5;
1634 if (CLHEP::RandFlat::shoot(rndmEngine)<0.75) {
1635 thetot = CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot_mean_narrow, tot_sigma_narrow);
1637 thetot = CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot_mean_wide, tot_sigma_wide);
1640 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.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
bool isValid(const T &p)
Av: we implement here an ATLAS-sepcific convention: all particles which are 99xxxxx are fine.
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
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.
void show() const
Print out in hex form.
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
int particleEncoding() const
double stepLength() const
const Amg::Vector3D & postLocalPosition() const
const Amg::Vector3D & localPosition() const
double kineticEnergy() const
double globalTime() const
double energyDeposit() const
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)
get a rotation transformation around Y-axis
const GenParticle * 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)