18#include "GaudiKernel/SystemOfUnits.h"
19#include "GaudiKernel/PhysicalConstants.h"
21#include "GeoModelHelpers/TransformToStringConverter.h"
41#include "GeoModelKernel/throwExcept.h"
44#include "CLHEP/Random/RandExponential.h"
45#include "CLHEP/Random/RandFlat.h"
46#include "CLHEP/Random/RandGaussZiggurat.h"
62 constexpr int N_Charge = 12;
63 constexpr int N_Velocity = 15;
64 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};
65 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};
66 constexpr double Eff_garfield[N_Charge][N_Velocity] = {
67 {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},
68 {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},
69 {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},
70 {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},
71 {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},
72 {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},
73 {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},
74 {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},
75 {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},
76 {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},
77 {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},
78 {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}};
80 validIndex(
int idx,
int arraySize){
81 return (idx>=0) and (idx<arraySize);
87 constexpr double SIG_VEL = 4.8;
138 return StatusCode::FAILURE;
155 ATH_MSG_DEBUG(
"Ready to read parameters for cluster simulation from file");
173 return StatusCode::SUCCESS;
179 SmartIF<IGeoModelSvc> geoModel{Gaudi::svcLocator()->service(
"GeoModelSvc")};
182 return StatusCode::FAILURE;
186 std::string atlasVersion = geoModel->atlasVersion();
188 SmartIF<IRDBAccessSvc> rdbAccess{Gaudi::svcLocator()->service(
"RDBAccessSvc")};
191 return StatusCode::FAILURE;
197 std::string configVal =
"";
199 IRDBRecordset_ptr atlasCommonRec = rdbAccess->getRecordsetPtr(
"AtlasCommon", atlasVersion,
"ATLAS");
200 if (atlasCommonRec->
size() == 0) {
203 configVal = (*atlasCommonRec)[0]->getString(
"CONFIG");
204 ATH_MSG_INFO(
"From DD Database, Configuration is " << configVal);
205 if (configVal ==
"RUN1") {
207 }
else if (configVal ==
"RUN2") {
209 }
else if (configVal ==
"RUN3") {
211 }
else if (configVal ==
"RUN4") {
214 if (
run == DataPeriod::Unknown) {
215 ATH_MSG_FATAL(
"Unexpected value for geometry config read from the database: " << configVal);
216 return StatusCode::FAILURE;
223 ATH_MSG_INFO(
"From Geometry DB: MuonSpectrometer configuration is: RUN1 or MuonGeometry = R.06");
225 ATH_MSG_INFO(
"From Geometry DB: MuonSpectrometer configuration is: RUN2 or MuonGeometry = R.07");
226 else if (
run == Run3)
227 ATH_MSG_INFO(
"From Geometry DB: MuonSpectrometer configuration is: RUN3 or MuonGeometry = R.09");
228 else if (
run == Run4)
229 ATH_MSG_INFO(
"From Geometry DB: MuonSpectrometer configuration is: RUN4 or MuonGeometry = R.10");
242 if (configVal ==
"RUN1") {
261 ATH_MSG_INFO(
"Run3/4: configuration parameter not from COOL");
268 ATH_MSG_INFO(
"RPC Run1/2/3-dependent configuration is enforced");
270 ATH_MSG_WARNING(
"Run1/2/3-dependent configuration is bypassed; be careful with option settings");
281 return StatusCode::SUCCESS;
284template <
class CondType>
287 const CondType* & condPtr)
const {
290 ATH_MSG_DEBUG(
"No key has been configured for object "<<
typeid(CondType).name()<<
". Clear pointer");
292 return StatusCode::SUCCESS;
296 ATH_MSG_FATAL(
"Failed to load conditions object "<<key.fullKey()<<
".");
297 return StatusCode::FAILURE;
299 condPtr = readHandle.
cptr();
300 return StatusCode::SUCCESS;
309 m_thpcRPC = std::make_unique<TimedHitCollection<RPCSimHit>>();
312 return StatusCode::SUCCESS;
320 TimedHitCollList hitCollList;
323 hitCollList.empty()) {
325 return StatusCode::FAILURE;
330 TimedHitCollList::iterator iColl(hitCollList.begin());
331 TimedHitCollList::iterator endColl(hitCollList.end());
334 for (; iColl != endColl; ++iColl) {
338 ATH_MSG_DEBUG(
"RPCSimHitCollection found with " << hitCollPtr->
size() <<
" hits");
341 m_thpcRPC->insert(timeIndex, hitCollPtr);
345 return StatusCode::SUCCESS;
362 if (!hitCollection.
isValid()) {
363 ATH_MSG_ERROR(
"Could not get RPCSimHitCollection container " << hitCollection.
name() <<
" from store "
364 << hitCollection.
store());
365 return StatusCode::FAILURE;
369 m_thpcRPC = std::make_unique<TimedHitCollection<RPCSimHit>>(1);
371 ATH_MSG_DEBUG(
"RPCSimHitCollection found with " << hitCollection->size() <<
" hits");
373 return StatusCode::SUCCESS;
376 TimedHitCollList hitCollList;
380 return StatusCode::FAILURE;
382 if (hitCollList.empty()) {
384 return StatusCode::FAILURE;
390 m_thpcRPC = std::make_unique<TimedHitCollection<RPCSimHit>>();
392 TimedHitCollList::iterator iColl(hitCollList.begin());
393 TimedHitCollList::iterator endColl(hitCollList.end());
394 while (iColl != endColl) {
396 m_thpcRPC->insert(iColl->first, p_collection);
401 return StatusCode::SUCCESS;
406 StatusCode status = StatusCode::SUCCESS;
416 ATH_CHECK(sdoContainer.
record(std::make_unique<MuonSimDataCollection>()));
425 if (status.isFailure()) {
ATH_MSG_ERROR(
"doDigitization Failed"); }
426 for (
size_t coll_hash = 0; coll_hash < collections.size(); ++coll_hash) {
427 if (collections[coll_hash]) {
428 ATH_CHECK( digitContainer->addCollection (collections[coll_hash].release(), coll_hash) );
440 StatusCode status = StatusCode::SUCCESS;
453 ATH_CHECK(sdoContainer.
record(std::make_unique<MuonSimDataCollection>()));
462 if (StatusCode::FAILURE == status) {
470 for (
size_t coll_hash = 0; coll_hash < collections.size(); ++coll_hash) {
471 if (collections[coll_hash]) {
472 ATH_CHECK( digitContainer->addCollection (collections[coll_hash].release(), coll_hash) );
484 rngWrapper->
setSeed(name(), ctx);
485 CLHEP::HepRandomEngine* rndmEngine = rngWrapper->
getEngine(ctx);
491 std::unique_ptr<RPCSimHitCollection> inputSimHitColl{std::make_unique<RPCSimHitCollection>(
"RPC_Hits")};
501 return StatusCode::FAILURE;
504 struct SimDataContent {
506 std::vector<MuonSimData::Deposit> deposits;
511 while (
m_thpcRPC->nextDetectorElement(i, e)) {
514 std::map<Identifier, SimDataContent> channelSimDataMap;
525 const int idHit = hit.
RPCid();
527 const double globalHitTime{
hitTime(phit)};
531 const double bunchTime{globalHitTime - hit.
globalTime()};
533 ATH_MSG_DEBUG(
"Global time " << globalHitTime <<
" G4 time " << G4Time <<
" Bunch time " << bunchTime);
536 ATH_MSG_VERBOSE(
"Validation: globalHitTime, G4Time, BCtime = " << globalHitTime <<
" " << G4Time <<
" " << bunchTime);
537 inputSimHitColl->Emplace(idHit, globalHitTime, hit.
localPosition(),
544 const std::string stationName =
m_muonHelper->GetStationName(idHit);
546 const int stationPhi =
m_muonHelper->GetPhiSector(idHit);
549 const int doubletPhi =
m_muonHelper->GetDoubletPhi(idHit);
558 ATH_MSG_WARNING(
"Failed to construct the element ID from "<<stationName
559 <<
", stationEta: "<<stationEta<<
", stationPhi: "<<stationPhi<<
", doubletR: "<<doubletR);
564 <<
" stationName " << stationName <<
" stationEta " << stationEta <<
" stationPhi " << stationPhi <<
" doubletR "
565 << doubletR <<
" doubletZ " << doubletZ <<
" doubletPhi " << doubletPhi <<
" gasGap " << gasGap);
573 gasGap = gasGap == 1 ? 2 : 1;
577 bool isValidEta{
false}, isValidPhi{
false};
578 const Identifier idpaneleta =
m_idHelper->channelID(elementID, doubletZ, doubletPhi, gasGap, 0, 1, isValidEta);
579 const Identifier idpanelphi =
m_idHelper->channelID(elementID, doubletZ, doubletPhi, gasGap, 1, 1, isValidPhi);
580 if (!isValidEta || !isValidPhi) {
582 <<
" stationName " << stationName <<
" stationEta " << stationEta <<
" stationPhi " << stationPhi
583 <<
" doubletR " << doubletR <<
" doubletZ " << doubletZ <<
" doubletPhi " << doubletPhi <<
" gasGap "
592 const double corrtimejitter = tmp_CorrJitter > 0.01 ?
593 CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0., tmp_CorrJitter) : 0.;
603 std::array<int, 3> pcseta =
physicalClusterSize(ctx, reEle, idpaneleta, gapCentre, rndmEngine);
604 ATH_MSG_VERBOSE(
"Simulated cluster on eta panel: size/first/last= " << pcseta[0] <<
"/" << pcseta[1] <<
"/" << pcseta[2]);
605 std::array<int, 3> pcsphi =
physicalClusterSize(ctx, reEle, idpanelphi, gapCentre, rndmEngine);
606 ATH_MSG_VERBOSE(
"Simulated cluster on phi panel: size/first/last= " << pcsphi[0] <<
"/" << pcsphi[1] <<
"/" << pcsphi[2]);
611 const Identifier atlasRpcIdeta =
m_idHelper->channelID(elementID, doubletZ, doubletPhi, gasGap, 0, pcseta[1], isValidEta);
612 const Identifier atlasRpcIdphi =
m_idHelper->channelID(elementID, doubletZ, doubletPhi, gasGap, 1, pcsphi[1], isValidPhi);
615 const auto [etaStripOn, phiStripOn] =
detectionEfficiency(ctx, idpaneleta, idpanelphi, rndmEngine, particleLink);
616 ATH_MSG_DEBUG(
"SetPhiOn " << phiStripOn <<
" SetEtaOn " << etaStripOn);
618 for (
bool imeasphi : {
false,
true}) {
619 if (!imeasphi && (!etaStripOn || !isValidEta))
continue;
620 if (imeasphi && (!phiStripOn || !isValidPhi))
continue;
624 const Identifier& atlasId = !imeasphi ? atlasRpcIdeta : atlasRpcIdphi;
625 std::array<int, 3> pcs{!imeasphi ? pcseta : pcsphi};
627 ATH_MSG_DEBUG(
"SetOn: stationName " << stationName <<
" stationEta " << stationEta <<
" stationPhi " << stationPhi
628 <<
" doubletR " << doubletR <<
" doubletZ " << doubletZ <<
" doubletPhi " << doubletPhi
629 <<
" gasGap " << gasGap <<
" measphi " << imeasphi);
637 ATH_MSG_DEBUG(
"Simulated cluster1: size/first/last= " << pcs[0] <<
"/" << pcs[1] <<
"/" << pcs[2]);
644 <<
" hit "<<
m_idHelper->print_to_string(atlasId)
656 double tns = G4Time + proptime + corrtimejitter;
657 ATH_MSG_VERBOSE(
"TOF+propagation time " << tns <<
" /s where proptime " << proptime <<
"/s");
659 double time = tns + bunchTime;
663 long long int packedMCword =
PackMCTruth(proptime, bunchTime, pos.y(), pos.z());
665 double* b =
reinterpret_cast<double*
>(&packedMCword);
677 if (channelSimDataMap.find(atlasId) == channelSimDataMap.end()) {
678 SimDataContent& content = channelSimDataMap[atlasId];
679 content.channelId = atlasId;
680 content.deposits.push_back(deposit);
681 content.gpos = reEle->
transform(atlasId)*
683 content.simTime =
hitTime(phit);
684 ATH_MSG_VERBOSE(
"adding SDO entry: r " << content.gpos.perp() <<
" z " << content.gpos.z());
696 for (
int clus = pcs[1]; clus <= pcs[2]; ++clus) {
697 Identifier newId =
m_idHelper->channelID(stationName, stationEta, stationPhi, doubletR, doubletZ,
698 doubletPhi, gasGap, imeasphi, clus,
isValid);
700 ATH_MSG_WARNING(__FILE__<<
":"<<__LINE__<<
"Channel "<< stationName<<
" "<<stationEta<<
" "<<stationPhi<<
" "<< doubletR<<
" "<<doubletZ
701 <<
" "<< doubletPhi<<
" "<< gasGap <<
" "<< imeasphi<<
" "<< clus<<
" is invalid");
706 if (stationName.find(
"BI") != std::string::npos) {
707 ATH_MSG_WARNING(
"Temporary skipping creation of RPC digit for stationName="
708 << stationName <<
", eta=" << stationEta <<
", phi=" << stationPhi <<
", doubletR=" << doubletR
709 <<
", doubletZ=" << doubletZ <<
", doubletPhi=" << doubletPhi <<
", gasGap=" << gasGap
710 <<
", measuresPhi=" << imeasphi <<
", strip=" << clus <<
", cf. ATLASRECTS-6124");
711 return StatusCode::SUCCESS;
715 return StatusCode::FAILURE;
724 std::vector<MuonSimData::Deposit> newdeps;
725 newdeps.push_back(deposit);
735 for (
auto it = channelSimDataMap.begin(); it != channelSimDataMap.end(); ++it) {
737 simData.setPosition(it->second.gpos);
738 simData.setTime(it->second.simTime);
739 auto insertResult = sdoContainer->insert(std::make_pair(it->first,
simData));
740 if (!insertResult.second)
741 ATH_MSG_WARNING(
"Attention: this sdo is not recorded, since the identifier already exists in the sdoContainer map");
757 const std::vector<MuonSimData::Deposit> theDeps = (*map_iter).second;
761 std::multimap<double, MuonSimData::Deposit> times;
764 for (
unsigned int k = 0; k < theDeps.size(); k++) {
765 double time = theDeps[k].second.secondEntry();
766 times.insert(std::multimap<double, MuonSimData::Deposit>::value_type(time, theDeps[k]));
773 std::multimap<double, MuonSimData::Deposit>::iterator map_dep_iter = times.begin();
776 double last_time = -10000;
777 for (; map_dep_iter != times.end(); ++map_dep_iter) {
778 double currTime = (*map_dep_iter).first;
784 if (sdoContainer->find(theId) != sdoContainer->end())
786 std::map<Identifier, MuonSimData>::const_iterator it = sdoContainer->find(theId);
787 std::vector<MuonSimData::Deposit> deps = ((*it).second).getdeposits();
788 deps.push_back((*map_dep_iter).second);
791 std::vector<MuonSimData::Deposit> deposits;
792 deposits.push_back((*map_dep_iter).second);
793 std::pair<std::map<Identifier, MuonSimData>::iterator,
bool> insertResult =
794 sdoContainer->insert(std::make_pair(theId,
MuonSimData(deposits, 0)));
795 if (!insertResult.second)
797 "Attention TEMP: this sdo is not recorded, since the identifier already exists in the sdoContainer map");
801 if (std::abs(currTime - last_time) > (
m_deadTime)) {
802 ATH_MSG_DEBUG(
"deposit with time " << currTime <<
" is distant enough from previous (if any) hit on teh same strip");
803 last_time = (*map_dep_iter).first;
806 double uncorrjitter = 0;
809 if (tmp_UncorrJitter > 0.01) uncorrjitter = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0., tmp_UncorrJitter);
819 double newDigit_time = currTime + uncorrjitter +
m_rpc_time_shift - tp - propTimeFromStripCenter;
821 double digi_ToT = -1.;
824 ATH_MSG_VERBOSE(
"last_time=currTime " << last_time <<
" jitter " << uncorrjitter <<
" TOFcorrection " << tp <<
" shift "
828 bool outsideDigitizationWindow =
outsideWindow(newDigit_time);
829 if (outsideDigitizationWindow) {
830 ATH_MSG_VERBOSE(
"hit outside digitization window - do not produce digits");
839 last_time = (*map_dep_iter).first;
841 std::unique_ptr<RpcDigit> newDigit = std::make_unique<RpcDigit>(theId, newDigit_time, digi_ToT,
false);
847 if (
m_idHelper->get_hash(elemId, coll_hash, &rpcContext)) {
848 ATH_MSG_ERROR(
"Unable to get RPC hash id from RPC Digit collection "
849 <<
"context begin_index = " << rpcContext.
begin_index()
850 <<
" context end_index = " << rpcContext.
end_index() <<
" the identifier is ");
858 if (coll_hash >= collections.size()) {
859 collections.resize (coll_hash+1);
861 digitCollection = collections[coll_hash].
get();
862 if (!digitCollection) {
863 collections[coll_hash] = std::make_unique<RpcDigitCollection>(elemId, coll_hash);
864 digitCollection = collections[coll_hash].
get();
866 digitCollection->
push_back(std::move(newDigit));
870 if (sdoContainer->find(theId) != sdoContainer->end()) {
871 std::map<Identifier, MuonSimData>::const_iterator it = sdoContainer->find(theId);
872 std::vector<MuonSimData::Deposit> deps = ((*it).second).getdeposits();
873 deps.push_back((*map_dep_iter).second);
875 std::vector<MuonSimData::Deposit> deposits;
876 deposits.push_back((*map_dep_iter).second);
877 std::pair<std::map<Identifier, MuonSimData>::iterator,
bool> insertResult =
878 sdoContainer->insert(std::make_pair(theId,
MuonSimData(deposits, 0)));
879 if (!insertResult.second)
881 "Attention: this sdo is not recorded, since teh identifier already exists in the sdoContainer map");
886 ATH_MSG_DEBUG(
"discarding digit due to dead time: " << (*map_dep_iter).first <<
" " << last_time);
898 return StatusCode::SUCCESS;
915 (flip ?
Amg::getRotateY3D(180.*Gaudi::Units::deg) : Amg::Transform3D::Identity())};
926 CLHEP::HepRandomEngine* rndmEngine)
const {
929 std::array<int, 3>
result{};
933 const int doubletPhi =
m_idHelper->doubletPhi(
id);
935 const bool measuresPhi =
m_idHelper->measuresPhi(
id);
936 const double pitch= ele->
StripPitch(measuresPhi);
939 const int nstrip = ele->
stripNumber(position.block<2,1>(0,0),
id);
940 const int numStrips = ele->
Nstrips(measuresPhi);
945 if (nstrip < 1 || nstrip > numStrips) {
949 float xstripnorm = (locStripPos -position).
x() / pitch ;
962 std::array<int, 3>&& pcs,
970 }
else if (pcs[0] == 2) {
972 }
else if (pcs[0] > 2) {
973 pcs[1] = pcs[1] - pcs[0] / 2;
974 if (fmod(pcs[0], 2) == 0) pcs[1] = pcs[1] + 1;
975 pcs[2] = pcs[1] + pcs[0] - 1;
976 }
else if (pcs[0] < -2) {
977 pcs[1] = pcs[1] + pcs[0] / 2;
978 pcs[2] = pcs[1] - pcs[0] - 1;
983 pcs[1] = std::clamp(pcs[1], 1, nstrips);
984 pcs[2] = std::clamp(pcs[2], 1, nstrips);
986 pcs[0] = pcs[2] - pcs[1] + 1;
1004 return std::abs(distance * SIG_VEL * 1.e-3);
1011 ATH_MSG_WARNING(
"A poblem: packing a propagation time <0 " << proptime <<
" redefine it as 0");
1014 long long int new_proptime = int(proptime * 10) & 0xff;
1020 long long int new_bctime = int((bctime + 300.) * 10.) & 0xffff;
1025 long long int new_posy = int((posy + 1500.) * 10.) & 0xffff;
1030 long long int new_posz = int((posz + 1500.) * 10.) & 0xffff;
1032 return (new_proptime + (new_bctime << 8) + (new_posy << 24) + (new_posz << 40));
1038 using Repacker =
union
1046 MCTruth.dWord = theWord;
1047 proptime = ((MCTruth.iWord) & 0x00000000000000ffLL) / 10.;
1048 bctime = (((MCTruth.iWord) & 0x0000000000ffff00LL) >> 8) / 10.;
1049 posy = (((MCTruth.iWord) & 0x000000ffff000000LL) >> 24) / 10.;
1050 posz = (((MCTruth.iWord) & 0x00ffff0000000000LL) >> 40) / 10.;
1053 bctime = bctime - 300.;
1054 posy = posy - 1500.;
1055 posz = posz - 1500.;
1061 SmartIF<ITagInfoMgr> tagInfoMgr{Gaudi::svcLocator()->service(
"TagInfoMgr")};
1062 if (!tagInfoMgr) {
return StatusCode::FAILURE; }
1064 std::string RpctimeSchema =
"";
1065 std::stringstream RpctimeShift;
1069 RpctimeSchema =
"Datalike_TOFoff_TimeShift" + RpctimeShift.str() +
"nsec";
1071 RpctimeSchema =
"G4like_TOFon_TimeShift" + RpctimeShift.str() +
"nsec";
1076 if (
sc.isFailure()) {
1083 return StatusCode::SUCCESS;
1091 CLHEP::HepRandomEngine* rndmEngine,
1096 ATH_MSG_DEBUG(
"RpcDigitizationTool::in DetectionEfficiency");
1104 float maxGeomEff{0.99}, PhiAndEtaEff{0.99}, OnlyEtaEff{0.f}, OnlyPhiEff{0.f};
1107 int stationName =
m_idHelper->stationName(IdEta);
1108 int stationEta =
m_idHelper->stationEta(IdEta);
1113 return std::make_pair(
false,
false);
1118 return std::make_pair(
true,
true);
1120 bool etaStripOn{
true}, phiStripOn{
true};
1125 unsigned int index = stationName - 2;
1127 if (stationName > 5 && stationName < 50)
index =
index - 2;
1129 else if (stationName > 50)
1135 THROW_EXCEPTION(
"Index out of array in Detection Efficiency SideA " <<
index <<
" stationName = " << stationName);
1142 if (stationEta < 0) {
1144 THROW_EXCEPTION(
"Index out of array in Detection Efficiency SideC " <<
index <<
" stationName = " << stationName);
1161 ATH_MSG_DEBUG(
"Efficiencies and cluster size + dead strips will be extracted from COOL");
1163 double FracDeadStripEta{0.}, FracDeadStripPhi{0.};
1164 double EtaPanelEfficiency{1.}, PhiPanelEfficiency{1.}, GapEfficiency{1.};
1165 int RPC_ProjectedTracksEta = 0;
1167 std::optional<double> fracDeadStripEtaFromCOOL = readCdo->
getFracDeadStrip(IdEta);
1168 std::optional<double> fracDeadStripPhiFromCOOL = readCdo->
getFracDeadStrip(IdPhi);
1170 bool noEntryInDb = !fracDeadStripEtaFromCOOL || !fracDeadStripPhiFromCOOL;
1172 FracDeadStripEta = fracDeadStripEtaFromCOOL.value_or(0.);
1173 FracDeadStripPhi = fracDeadStripPhiFromCOOL.value_or(0.);
1176 EtaPanelEfficiency = readCdo->
getEfficiency(IdEta).value_or(1.);
1177 PhiPanelEfficiency = readCdo->
getEfficiency(IdPhi).value_or(1.);
1180 if (std::abs(FracDeadStripEta - 1.) < 0.001) {
1181 ATH_MSG_DEBUG(
"Watch out: SPECIAL CASE: Read from Cool: FracDeadStripEta/Phi "
1182 << FracDeadStripEta <<
"/" << FracDeadStripPhi <<
" RPC_ProjectedTracksEta " << RPC_ProjectedTracksEta
1183 <<
" Eta/PhiPanelEfficiency " << EtaPanelEfficiency <<
"/" << PhiPanelEfficiency <<
" gapEff " << GapEfficiency
1187 FracDeadStripPhi = 0.;
1188 ATH_MSG_VERBOSE(
"Watch out: SPECIAL CASE: Resetting FracDeadStripPhi " << FracDeadStripPhi <<
" ignoring phi dead strips ");
1196 bool changing =
false;
1197 ATH_MSG_DEBUG(
"Read from Cool: FracDeadStripEta/Phi " << FracDeadStripEta <<
"/" << FracDeadStripPhi <<
" RPC_ProjectedTracksEta "
1198 << RPC_ProjectedTracksEta <<
" Eta/PhiPanelEfficiency " << EtaPanelEfficiency
1199 <<
"/" << PhiPanelEfficiency <<
" gapEff " << GapEfficiency);
1201 if ((maxGeomEff - FracDeadStripEta) - EtaPanelEfficiency < -0.011) {
1202 ATH_MSG_DEBUG(
"Ineff. from dead strips on Eta Panel larger that measured efficiency: deadFrac="
1203 << FracDeadStripEta <<
" Panel Eff=" << EtaPanelEfficiency <<
" for Panel " <<
m_idHelper->show_to_string(IdEta));
1204 ATH_MSG_DEBUG(
"... see the corresponding report from RpcDetectorStatusDbTool");
1206 EtaPanelEfficiency = maxGeomEff - FracDeadStripEta;
1210 if ((maxGeomEff - FracDeadStripPhi) - PhiPanelEfficiency < -0.011) {
1211 ATH_MSG_DEBUG(
"Ineff. from dead strips on Phi Panel larger that measured efficiency: deadFrac="
1212 << FracDeadStripPhi <<
" Panel Eff=" << PhiPanelEfficiency <<
" for Panel " <<
m_idHelper->show_to_string(IdPhi));
1213 ATH_MSG_DEBUG(
"... see the corresponding report among the warnings of RpcDetectorStatusDbTool");
1215 PhiPanelEfficiency = maxGeomEff - FracDeadStripPhi;
1219 if ((maxGeomEff - FracDeadStripEta * FracDeadStripPhi) - GapEfficiency < -0.011) {
1220 ATH_MSG_DEBUG(
"Ineff. from dead strips on Eta/Phi Panels larger that measured EtaORPhi efficiency: deadFrac="
1221 << FracDeadStripEta * FracDeadStripPhi <<
" EtaORPhi Eff=" << GapEfficiency <<
" for GasGap "
1223 ATH_MSG_DEBUG(
"... see the corresponding report among the warnings of RpcDetectorStatusDbTool");
1225 GapEfficiency = maxGeomEff - FracDeadStripEta * FracDeadStripPhi;
1229 ATH_MSG_DEBUG(
"Rinormalized Values from Cool: FracDeadStripEta/Phi "
1230 << FracDeadStripEta <<
"/" << FracDeadStripPhi <<
" RPC_ProjectedTracksEta " << RPC_ProjectedTracksEta
1231 <<
" Eta/PhiPanelEfficiency " << EtaPanelEfficiency <<
"/" << PhiPanelEfficiency <<
" gapEff " << GapEfficiency);
1235 if ((FracDeadStripEta > 0.0 && FracDeadStripEta < 1.0) || (FracDeadStripPhi > 0.0 && FracDeadStripPhi < 1.0) || (noEntryInDb)) {
1236 EtaPanelEfficiency = EtaPanelEfficiency / (maxGeomEff - FracDeadStripEta);
1237 PhiPanelEfficiency = PhiPanelEfficiency / (maxGeomEff - FracDeadStripPhi);
1238 GapEfficiency = GapEfficiency / (maxGeomEff - FracDeadStripEta * FracDeadStripPhi);
1240 if (EtaPanelEfficiency > maxGeomEff) EtaPanelEfficiency = maxGeomEff;
1241 if (PhiPanelEfficiency > maxGeomEff) PhiPanelEfficiency = maxGeomEff;
1242 if (GapEfficiency > maxGeomEff) GapEfficiency = maxGeomEff;
1244 if (EtaPanelEfficiency > GapEfficiency) GapEfficiency = EtaPanelEfficiency;
1245 if (PhiPanelEfficiency > GapEfficiency) GapEfficiency = PhiPanelEfficiency;
1246 ATH_MSG_DEBUG(
"Eff Redefined (to correct for deadfrac): FracDeadStripEta/Phi "
1247 <<
" Eta/PhiPanelEfficiency " << EtaPanelEfficiency <<
"/" << PhiPanelEfficiency <<
" gapEff "
1253 PhiAndEtaEff = float(EtaPanelEfficiency + PhiPanelEfficiency - GapEfficiency);
1254 if (PhiAndEtaEff < 0.) PhiAndEtaEff = 0.;
1255 OnlyEtaEff = float(EtaPanelEfficiency - PhiAndEtaEff);
1256 if (OnlyEtaEff < 0.) OnlyEtaEff = 0.;
1257 OnlyPhiEff = float(PhiPanelEfficiency - PhiAndEtaEff);
1258 if (OnlyPhiEff < 0.) OnlyPhiEff = 0.;
1262 bool applySpecialPatch =
false;
1268 applySpecialPatch =
true;
1270 "Applying special patch for BMS at |eta|=6 lowPt plane -dbbZ=2 and dbPhi=1 ... will use default eff. for Id "
1273 "Applying special patch: THIS HAS TO BE DONE IF /RPC/DQMF/ELEMENT_STATUS tag is "
1274 "RPCDQMFElementStatus_2012_Jaunuary_2");
1280 if (applySpecialPatch || RPC_ProjectedTracksEta < m_CutProjectedTracks || RPC_ProjectedTracksEta > 10000000 ||
1281 EtaPanelEfficiency > 1 || EtaPanelEfficiency < 0 || PhiPanelEfficiency > 1 || PhiPanelEfficiency < 0 || GapEfficiency > 1 ||
1282 GapEfficiency < 0) {
1284 THROW_EXCEPTION(
"Index out of array in Detection Efficiency SideA COOLDB" <<
index <<
" stationName = " << stationName);
1288 <<
" resetting eff. from cool with default(python) values ");
1294 if (stationEta < 0) {
1296 THROW_EXCEPTION(
"Index out of array in Detection Efficiency SideC COOLDB" <<
index <<
" stationName = " << stationName);
1305 float effgap = PhiAndEtaEff + OnlyEtaEff + OnlyPhiEff;
1306 float s_EtaPanelEfficiency = 1. - FracDeadStripEta;
1307 float s_PhiPanelEfficiency = 1. - FracDeadStripPhi;
1308 float s_PhiAndEtaEff = s_EtaPanelEfficiency * s_PhiPanelEfficiency / effgap;
1309 if (s_PhiAndEtaEff < PhiAndEtaEff) PhiAndEtaEff = s_PhiAndEtaEff;
1310 float s_OnlyEtaEff = s_EtaPanelEfficiency - PhiAndEtaEff;
1311 float s_OnlyPhiEff = s_PhiPanelEfficiency - PhiAndEtaEff;
1313 if (s_OnlyEtaEff < OnlyEtaEff) OnlyEtaEff = s_OnlyEtaEff;
1314 if (s_OnlyPhiEff < OnlyPhiEff) OnlyPhiEff = s_OnlyPhiEff;
1318 float VolEff = PhiAndEtaEff + OnlyEtaEff + OnlyPhiEff;
1319 if (VolEff > maxGeomEff) {
1320 PhiAndEtaEff = (PhiAndEtaEff / VolEff) * maxGeomEff;
1321 OnlyEtaEff = (OnlyEtaEff / VolEff) * maxGeomEff;
1322 OnlyPhiEff = (OnlyPhiEff / VolEff) * maxGeomEff;
1335 PhiAndEtaEff = PhiAndEtaEff * eff_sf;
1336 OnlyEtaEff = OnlyEtaEff * eff_sf;
1337 OnlyPhiEff = OnlyPhiEff * eff_sf;
1341 float I0 = PhiAndEtaEff;
1342 float I1 = PhiAndEtaEff + OnlyEtaEff;
1343 float ITot = PhiAndEtaEff + OnlyEtaEff + OnlyPhiEff;
1345 float GapEff = ITot ;
1346 float PhiEff = PhiAndEtaEff + OnlyPhiEff;
1347 float EtaEff = PhiAndEtaEff + OnlyEtaEff;
1349 ATH_MSG_DEBUG(
"DetectionEfficiency: Final Efficiency Values applied for "
1350 <<
m_idHelper->show_to_string(IdEta) <<
" are " << PhiAndEtaEff <<
"=PhiAndEtaEff " << OnlyEtaEff
1351 <<
"=OnlyEtaEff " << OnlyPhiEff <<
"=OnlyPhiEff " << GapEff <<
"=GapEff " << EtaEff <<
"=EtaEff " << PhiEff
1354 float rndmEff = CLHEP::RandFlat::shoot(rndmEngine, 1);
1359 }
else if ((I0 <= rndmEff) && (rndmEff < I1)) {
1362 }
else if ((I1 <= rndmEff) && (rndmEff <= ITot)) {
1370 return std::make_pair(etaStripOn, phiStripOn);
1377 CLHEP::HepRandomEngine* rndmEngine)
const {
1378 ATH_MSG_DEBUG(
"RpcDigitizationTool::in determineClusterSize");
1382 int ClusterSize = 1;
1384 double FracClusterSize1{1.}, FracClusterSize2{0.}, MeanClusterSize{1.},
1385 FracClusterSizeTail{0.}, MeanClusterSizeTail{1.},
1386 FracClusterSize2norm{0.};
1389 int stationName =
m_idHelper->stationName(idRpcStrip);
1390 int stationEta =
m_idHelper->stationEta(idRpcStrip);
1391 int measuresPhi =
m_idHelper->measuresPhi(idRpcStrip);
1393 unsigned int index = stationName - 2;
1395 if (stationName > 5 && stationName < 50)
index =
index - 2;
1397 else if (stationName > 50)
1407 ATH_MSG_ERROR(
"Index out of array in determineClusterSize SideA " <<
index <<
" statName " << stationName);
1415 if (stationEta < 0) {
1421 ATH_MSG_ERROR(
"Index out of array in determineClusterSize SideC " <<
index <<
" statName " << stationName);
1446 ATH_MSG_DEBUG(
"FracClusterSize1 and 2 " << FracClusterSize1 <<
" " << FracClusterSize2);
1448 FracClusterSizeTail = 1. - FracClusterSize1 - FracClusterSize2;
1450 MeanClusterSizeTail = MeanClusterSize - FracClusterSize1 - 2 * FracClusterSize2;
1452 ATH_MSG_DEBUG(
"MeanClusterSizeTail and FracClusterSizeTail " << MeanClusterSizeTail <<
" " << FracClusterSizeTail);
1455 if (RPC_ProjectedTracks < m_CutProjectedTracks || RPC_ProjectedTracks > 10000000 || MeanClusterSize >
m_CutMaxClusterSize ||
1456 MeanClusterSize <= 1 || FracClusterSizeTail < 0 || FracClusterSize1 < 0 || FracClusterSize2 < 0 || FracClusterSizeTail > 1 ||
1457 FracClusterSize1 > 1 || FracClusterSize2 > 1) {
1458 if (stationName >= 2) {
1464 ATH_MSG_ERROR(
"Index out of array in determineClusterSize SideA " <<
index <<
" statName " << stationName);
1472 if (stationEta < 0) {
1476 ATH_MSG_ERROR(
"Index out of array in determineClusterSize SideC " <<
index <<
" statName " << stationName);
1493 FracClusterSize1 = std::min(FracClusterSize1, 1.);
1494 FracClusterSize2 = std::min(FracClusterSize2, 1.);
1495 FracClusterSizeTail = std::min(FracClusterSizeTail, 1.);
1496 float FracTot = FracClusterSize1 + FracClusterSize2 + FracClusterSizeTail;
1497 if (FracTot != 1. && FracTot > 0) {
1498 FracClusterSize1 = FracClusterSize1 / FracTot;
1499 FracClusterSize2 = FracClusterSize2 / FracTot;
1500 FracClusterSizeTail = FracClusterSizeTail / FracTot;
1502 if (MeanClusterSizeTail < 0 || MeanClusterSizeTail > 10) MeanClusterSizeTail = 1;
1504 ATH_MSG_VERBOSE(
"ClusterSize Final " << FracClusterSize1 <<
" FracClusterSize1 " << FracClusterSize2 <<
" FracClusterSize2 "
1505 << FracClusterSizeTail <<
" " << FracClusterSizeTail <<
" MeanClusterSizeTail "
1506 << MeanClusterSizeTail);
1508 float FracClusterSize1plus2 = FracClusterSize1 + FracClusterSize2;
1509 float ITot = FracClusterSize1 + FracClusterSize2 + FracClusterSizeTail;
1511 if (FracClusterSize1plus2 != 0) {
1513 FracClusterSize2norm = FracClusterSize2 / FracClusterSize1plus2;
1516 float rndmCS = CLHEP::RandFlat::shoot(rndmEngine, ITot);
1518 if (stationName >= 2) {
1520 if (rndmCS < FracClusterSize1plus2) {
1522 if (xstripnorm <= FracClusterSize2norm / 2. * 1.3) {
1524 }
else if ((1.0 - FracClusterSize2norm / 2. * 1.3) <= xstripnorm) {
1530 float rndmCS1_2 = CLHEP::RandFlat::shoot(rndmEngine, 1);
1531 ClusterSize = 1 + (rndmCS1_2 < FracClusterSize2norm);
1534 }
else if ((FracClusterSize1plus2 <= rndmCS) && (rndmCS <= ITot)) {
1536 ClusterSize += int(CLHEP::RandExponential::shoot(rndmEngine, MeanClusterSizeTail));
1537 float rndmLR = CLHEP::RandFlat::shoot(rndmEngine, 1.0);
1538 if (rndmLR > 0.5) ClusterSize = -ClusterSize;
1544 if (rndmCS < FracClusterSize1) {
1546 }
else if (rndmCS < FracClusterSize1 + FracClusterSize2) {
1549 ClusterSize = int(CLHEP::RandExponential::shoot(rndmEngine, MeanClusterSizeTail));
1551 ClusterSize = std::max(ClusterSize, 1);
1552 if (ClusterSize > 1) {
1553 float rndmLR = CLHEP::RandFlat::shoot(rndmEngine, 1.0);
1554 if (rndmLR > 0.5) ClusterSize = -ClusterSize;
1562 double qcharge = 1.;
1563 const int particlePdgId = genParticle->pdg_id();
1565 qcharge = (
static_cast<double>((std::abs(particlePdgId) / 1000) % 100)) / (
static_cast<double>((std::abs(particlePdgId) / 10) % 100));
1566 qcharge = ((
static_cast<double>((
static_cast<int>(qcharge * 100))))) / 100;
1567 if (particlePdgId < 0.0) qcharge = -qcharge;
1569 const double QPx = genParticle->momentum().px();
1570 const double QPy = genParticle->momentum().py();
1571 const double QPz = genParticle->momentum().pz();
1572 const double QE = genParticle->momentum().e();
1573 const double QM2 = std::pow(QE, 2) - std::pow(QPx, 2) - std::pow(QPy, 2) - std::pow(QPz, 2);
1574 const double QP = std::hypot(QPx, QPy, QPz);
1575 const double QM = QM2 >=0 ? std::sqrt(QM2) : -1.;
1577 const double qbetagamma = QM > 0. ? QP / QM : -1.;
1581 for (
int i = 0; i < 12; i++) {
1582 if (Charge[i] == std::abs(qcharge)) {
1587 int i_v = -99, j_v = 99;
1588 if (qbetagamma != -1) {
1589 for (
int i = 0; i < 15; i++) {
1590 if (Velocity[i] <= qbetagamma) { i_v = i; }
1592 for (
int i = 14; i >= 0; i--) {
1593 if (Velocity[i] >= qbetagamma) { j_v = i; }
1598 double eff_fcp = 1.0, eff_muon = 1.0;
1599 if (i_e >= 0 && i_e <= 11) {
1600 if (validIndex(j_v, N_Velocity) && validIndex(i_v, N_Velocity) && (j_v - i_v) == 1) {
1601 const double delta_v = Velocity[i_v] - Velocity[j_v];
1602 eff_fcp = (Eff_garfield[i_e][i_v] - Eff_garfield[i_e][j_v]) / delta_v * qbetagamma +
1603 (Eff_garfield[i_e][j_v] * Velocity[i_v] - Eff_garfield[i_e][i_v] * Velocity[j_v]) / delta_v;
1604 eff_muon = (Eff_garfield[11][i_v] - Eff_garfield[11][j_v]) / delta_v * qbetagamma +
1605 (Eff_garfield[11][j_v] * Velocity[i_v] - Eff_garfield[11][i_v] * Velocity[j_v]) / delta_v;
1606 }
else if (i_v == 14 && j_v == 99) {
1607 eff_fcp = Eff_garfield[i_e][14];
1608 eff_muon = Eff_garfield[11][14];
1609 }
else if (i_v == -99 && j_v == 0) {
1610 eff_fcp = Eff_garfield[i_e][0];
1611 eff_muon = Eff_garfield[11][0];
1613 ATH_MSG_WARNING(
"Wrong particle with unknown velocity! Scale factor is set to be 1.");
1616 ATH_MSG_WARNING(
"Wrong particle with unknown charge! Scale factor is set to be 1.");
1619 const double eff_SF = eff_fcp / eff_muon;
1626 constexpr double tot_mean_narrow = 16.;
1627 constexpr double tot_sigma_narrow = 2.;
1628 constexpr double tot_mean_wide = 15.;
1629 constexpr double tot_sigma_wide = 4.5;
1633 if (CLHEP::RandFlat::shoot(rndmEngine)<0.75) {
1634 thetot = CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot_mean_narrow, tot_sigma_narrow);
1636 thetot = CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot_mean_wide, tot_sigma_wide);
1639 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(std::ostream &out=std::cout) 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)
int run(int argc, char *argv[])