62 constexpr double s_inv_c_light(1. / Gaudi::Units::c_light);
104 ATH_MSG_DEBUG(
"Retrieved MuonGeoModelDetectorManager from StoreGate");
115 return StatusCode::FAILURE;
140 return StatusCode::SUCCESS;
144 ATH_MSG_DEBUG(
"MdtDigitizationTool::prepareEvent() called for " << nInputEvents <<
" input events");
147 m_thpcMDT = std::make_unique<TimedHitCollection<MDTSimHit>>();
149 return StatusCode::SUCCESS;
153 ATH_MSG_DEBUG(
"MdtDigitizationTool::processBunchXing() " << bunchXing);
156 TimedHitCollList hitCollList;
159 hitCollList.empty()) {
161 return StatusCode::FAILURE;
166 TimedHitCollList::iterator iColl(hitCollList.begin());
167 TimedHitCollList::iterator endColl(hitCollList.end());
170 for (; iColl != endColl; ++iColl) {
174 ATH_MSG_DEBUG(
"MDTSimHitCollection found with " << hitCollPtr->
size() <<
" hits");
177 m_thpcMDT->insert(timeIndex, hitCollPtr);
181 return StatusCode::SUCCESS;
193 if (!hitCollection.
isValid()) {
194 ATH_MSG_ERROR(
"Could not get MDTSimHitCollection container " << hitCollection.
name() <<
" from store "
195 << hitCollection.
store());
196 return StatusCode::FAILURE;
200 m_thpcMDT = std::make_unique<TimedHitCollection<MDTSimHit>>(1);
202 ATH_MSG_DEBUG(
"MDTSimHitCollection found with " << hitCollection->size() <<
" hits");
204 return StatusCode::SUCCESS;
208 TimedHitCollList hitCollList;
212 return StatusCode::FAILURE;
214 if (hitCollList.empty()) {
216 return StatusCode::FAILURE;
222 m_thpcMDT = std::make_unique<TimedHitCollection<MDTSimHit>>();
225 TimedHitCollList::iterator iColl(hitCollList.begin());
226 TimedHitCollList::iterator endColl(hitCollList.end());
227 while (iColl != endColl) {
229 m_thpcMDT->insert(iColl->first, p_collection);
230 ATH_MSG_DEBUG(
"MDTSimHitCollection found with " << p_collection->
size() <<
" hits");
233 return StatusCode::SUCCESS;
238 std::string rngName = name() + streamName;
239 rngWrapper->
setSeed(rngName, ctx);
249 ATH_MSG_DEBUG(
"Recorded MdtDigitContainer called " << digitContainer.
name() <<
" in store " << digitContainer.
store());
253 ATH_CHECK(sdoContainer.
record(std::make_unique<MuonSimDataCollection>()));
254 ATH_MSG_DEBUG(
"Recorded MuonSimDataCollection called " << sdoContainer.
name() <<
" in store " << sdoContainer.
store());
258 if (status.isFailure()) {
ATH_MSG_ERROR(
"doDigitization Failed"); }
260 for (
size_t coll_hash = 0; coll_hash < collections.size(); ++coll_hash) {
261 if (collections[coll_hash]) {
262 ATH_CHECK( digitContainer->addCollection (collections[coll_hash].release(), coll_hash) );
267 std::vector<MDTSimHitCollection*>::iterator MDTHitColl =
m_MDTHitCollList.begin();
268 std::vector<MDTSimHitCollection*>::iterator MDTHitCollEnd =
m_MDTHitCollList.end();
269 while (MDTHitColl != MDTHitCollEnd) {
270 delete (*MDTHitColl);
284 ATH_MSG_DEBUG(
"Recorded MdtDigitContainer called " << digitContainer.
name() <<
" in store " << digitContainer.
store());
288 ATH_CHECK(sdoContainer.
record(std::make_unique<MuonSimDataCollection>()));
289 ATH_MSG_DEBUG(
"Recorded MuonSimDataCollection called " << sdoContainer.
name() <<
" in store " << sdoContainer.
store());
291 StatusCode status = StatusCode::SUCCESS;
294 if (StatusCode::FAILURE == status) {
303 for (
size_t coll_hash = 0; coll_hash < collections.size(); ++coll_hash) {
304 if (collections[coll_hash]) {
305 ATH_CHECK( digitContainer->addCollection (collections[coll_hash].release(), coll_hash) );
326 return StatusCode::FAILURE;
329 while (
m_thpcMDT->nextDetectorElement(i, e)) {
338 createDigits(ctx, collections, sdoContainer, rndmEngine);
346 return StatusCode::SUCCESS;
351 CLHEP::HepRandomEngine* toolRndmEngine) {
355 double globalHitTime(
hitTime(phit));
361 const int id = hit.
MDTid();
364 <<
" driftRadius " << driftRadius);
366 std::string stationName =
m_muonHelper->GetStationName(
id);
374 Identifier DigitId =
m_idHelperSvc->mdtIdHelper().channelID(stationName, stationEta, stationPhi, multilayer, layer, tube);
383 ATH_MSG_ERROR(
"MuonGeoManager does not return valid element for given id!");
399 driftRadius *=
result.trackingSign;
404 double distanceToRO = 0.;
411 MdtDigiToolInput digiInput(std::abs(driftRadius), distanceToRO, 0., 0., 0., 0., DigitId);
413 double qgamma = -9999.;
422 const double QE = genParticle->momentum().e();
423 const double QM2 = genParticle->momentum().m2();
425 qgamma = QE / std::sqrt(QM2);
430 digiInput =
MdtDigiToolInput{std::abs(driftRadius), distanceToRO, 0., 0., qcharge, qgamma, DigitId};
440 double driftTime = digiOutput.
driftTime();
441 double adc = digiOutput.
adc();
443 ATH_MSG_VERBOSE(
"Tube efficient: driftTime " << driftTime <<
" adc value " << adc);
451 if (distRO < 0.)
sign = 1.;
458 driftTime += propagation_delay;
459 ATH_MSG_VERBOSE(
"Position along wire: " << position_along_wire <<
" propagation delay: " << propagation_delay
460 <<
" new driftTime " << driftTime);
465 driftTime += globalHitTime;
466 ATH_MSG_VERBOSE(
"Time off Flight + bunch offset: " << globalHitTime <<
" new driftTime " << driftTime);
469 <<
" Drift time computation " << driftTime <<
" radius " << driftRadius <<
" adc " << adc);
474 <<
" driftRadius = " << driftRadius);
480 bool BOL4X13 =
false;
482 if (stationName ==
"BOL" && std::abs(stationEta) == 4 && stationPhi == 7 && multilayer == 1) { BOL4X13 =
true; }
488 double twin_sign_driftTime = 0.;
490 constexpr double HV_delay = 6.;
491 double twin_tubeLength{0.}, twin_geo_pos_along_wire{0.},
492 twin_sign_pos_along_wire{0.}, twin_sign{-1.};
495 if (tube % 4 == 1 || tube % 4 == 2)
496 twin_tube = tube + 2;
497 else if (tube % 4 == 0 || tube % 4 == 3)
498 twin_tube = tube - 2;
500 twin_DigitId =
m_idHelperSvc->mdtIdHelper().channelID(stationName, stationEta, stationPhi, multilayer, layer, twin_tube);
502 twin_tubeLength = element->
tubeLength(twin_DigitId);
505 if (distRO < 0.) twin_sign = 1.;
508 twin_sign_pos_along_wire = twin_sign * twin_geo_pos_along_wire;
509 double twin_propagation_delay = twin_sign * (1. /
m_signalSpeed) * twin_geo_pos_along_wire;
513 twin_sign_driftTime = driftTime + twin_tubeLength /
m_signalSpeed - 2 * twin_propagation_delay + HV_delay;
516 double rand = CLHEP::RandGaussZiggurat::shoot(twinRndmEngine, twin_sign_driftTime,
m_resTwin);
517 twin_sign_driftTime = rand;
519 ATH_MSG_DEBUG(
" TWIN TUBE stname " << stationName <<
" steta " << stationEta <<
" stphi " << stationPhi <<
" mLayer "
520 << multilayer <<
" layer " << layer <<
" tube " << tube
521 <<
" signed position along wire = " << twin_sign_pos_along_wire
522 <<
" propagation delay = " << twin_propagation_delay <<
" drifttime = " << driftTime
523 <<
" twin_driftTime = " << twin_sign_driftTime
524 <<
" TWIN time-difference = " << (twin_sign_driftTime - driftTime));
527 m_hits.insert(
mdt_hit_info(twin_DigitId, twin_sign_driftTime, adc, driftRadius, &phit));
534 <<
" radius " << driftRadius);
542 const int id = hit.
MDTid();
543 std::string stationName =
m_muonHelper->GetStationName(
id);
550 Identifier DigitId =
m_idHelperSvc->mdtIdHelper().channelID(stationName, stationEta, stationPhi, multilayer, layer, tube);
553 <<
" " << stationEta <<
" " << stationPhi);
562 if (!readCdo->isGood(DigitId))
return false;
566 double tubeL{0.}, tubeR{0.};
570 ATH_MSG_ERROR(
"MuonGeoManager does not return valid element for given id!");
603 CLHEP::HepRandomEngine* rndmEngine) {
604 Identifier currentDigitId{0}, currentElementId{0};
606 double currentDeadTime = 0.;
613 double timeOffsetEvent = 0.0;
614 double timeOffsetTotal = 0.0;
618 int inum = CLHEP::RandFlat::shootInt(rndmEngine, 0, 10);
620 timeOffsetEvent = -25.0;
621 }
else if (inum == 9) {
622 timeOffsetEvent = 25.0;
624 ATH_MSG_DEBUG(
"Emulating timing spead of cosmics: +/- 1 BC. Adding " << timeOffsetEvent <<
" ns to time");
629 if (!mdtCalibConstants.
isValid()) {
633 for (; it !=
m_hits.end(); ++it) {
639 if (elementId != currentElementId) {
640 currentElementId = elementId;
646 timeOffsetTotal = timeOffsetEvent + CLHEP::RandFlat::shoot(rndmEngine, -12.5, 12.5);
647 ATH_MSG_DEBUG(
"Emulating time jitter of cosmic ray muons w.r.t LVL1 accept. Adding " << timeOffsetTotal <<
" ns to time");
651 if (!digitCollection) {
656 float driftRadius = it->radius;
657 double driftTime = it->time;
663 if (idDigit != currentDigitId) {
664 currentDigitId = idDigit;
667 ATH_MSG_VERBOSE(
"New tube, setting dead time: " << currentDeadTime <<
" driftTime " << driftTime);
670 if (driftTime > currentDeadTime) {
673 ATH_MSG_VERBOSE(
"Additional hit, setting dead time: " << currentDeadTime <<
" driftTime " << driftTime);
676 ATH_MSG_VERBOSE(
"Hit within dead time: " << currentDeadTime <<
" driftTime " << driftTime);
689 if (insideMask && insideMatch) {
690 ATH_MSG_WARNING(
" Digit in matching AND masking window, please check window definition: relative time " << relativeTime);
693 if (insideMatch || insideMask) {
700 if (singleTubeData) {
708 int tdc =
digitizeTime(driftTime +
t0 + timeOffsetTotal, isHPTDC, rndmEngine);
711 <<
" driftRadius " << driftRadius <<
" TDC " << tdc <<
" ADC " << adc <<
" mask bit "
727 std::vector<MuonSimData::Deposit> deposits;
728 deposits.push_back(deposit);
730 const Amg::Vector3D& tempLocPos = (*(it->simhit))->localPosition();
731 Amg::Vector3D p = geo->localToGlobalTransf(idDigit)*tempLocPos;
734 sdoContainer->insert(std::make_pair(idDigit, tempSDO));
738 <<
" Digit Id = " <<
m_idHelperSvc->toString(idDigit) <<
" driftTime " << driftTime
739 <<
" --> hit ignored");
749 if (
m_idHelperSvc->mdtIdHelper().get_hash(elementId, coll_hash, &mdtContext)) {
750 ATH_MSG_ERROR(
"Unable to get MDT hash id from MDT Digit collection "
751 <<
"context begin_index = " << mdtContext.
begin_index() <<
" context end_index = " << mdtContext.
end_index()
752 <<
" the identifier is ");
756 if (coll_hash >= collections.size()) {
757 collections.resize (coll_hash+1);
760 auto& coll = collections[coll_hash];
762 coll = std::make_unique<MdtDigitCollection>(elementId, coll_hash);
770 tdcCount = CLHEP::RandGaussZiggurat::shoot(rndmEngine, tmpCount,
m_resTDC);
771 if (tdcCount < 0 || tdcCount > 4096) {
ATH_MSG_DEBUG(
" Count outside TDC window: " << tdcCount); }
779 double distanceToVertex(0.);
783 ATH_MSG_ERROR(
"MuonGeoManager does not return valid element for given id!");
785 distanceToVertex = element->
tubePos(DigitId).mag();
788 ATH_MSG_DEBUG(
"minimumTof calculated " << distanceToVertex * s_inv_c_light);
789 return distanceToVertex * s_inv_c_light;
842 double pointingCheck = gpos.dot(gdir) < 0 ? -1. : 1.;
843 if (pointingCheck < 0) { gdir *= pointingCheck; }
845 double trackingSign = 1.;
846 double localSag = 0.0;
851 trackingSign = lpsag[
Trk::locR] < 0 ? -1. : 1.;
865 double sign = lpos.dot(lgravDir) < 0 ? -1. : 1.;
867 return {
sign, trackingSign, lpos, localSag};
float hitTime(const AFP_SIDSimHit &hit)
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
double charge(const T &p)
char data[hepevt_bytes_allocation_ATLAS]
ATLAS-specific HepMC functions.
AtlasHitsVector< MDTSimHit > MDTSimHitCollection
HitVector::iterator HitIt
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.
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.
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
This is a "hash" representation of an Identifier.
void show() const
Print out in hex form.
void setLocalPosition(Amg::Vector3D &localPosition)
const Amg::Vector3D & localPosition() const
void setDriftRadius(double radius)
double driftRadius() const
const HepMcParticleLink & particleLink() const
std::string print() const
double globalTime() const
static const MdtHitIdHelper * GetHelper(unsigned int nTubes=78)
Amg::Vector3D tubePos(const Identifier &id) const
Returns the global position of the given tube.
Amg::Transform3D nodeform_localToGlobalTransf(const Identifier &id) const
Amg::Vector3D tubeFrame_localROPos(const int tubelayer, const int tube) const
virtual const Trk::Surface & surface() const override final
Return surface associated with this detector element.
double innerTubeRadius() const
Returns the inner tube radius excluding the aluminium walls.
const Amg::Transform3D & localToGlobalTransf(const Identifier &id) const
double tubeLength(const int tubeLayer, const int tube) const
Amg::Transform3D globalToLocalTransf(const int tubeLayer, const int tube) const
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
const MdtReadoutElement * getMdtReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
void setTime(const float &time)
std::pair< HepMcParticleLink, MuonMCData > Deposit
void setPosition(const Amg::Vector3D &pos)
const DataObjID & fullKey() const
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.
Class for a StraightLineSurface in the ATLAS detector to describe dirft tube and straw like detectors...
virtual bool globalToLocal(const Amg::Vector3D &glob, const Amg::Vector3D &mom, Amg::Vector2D &loc) const override final
Specified for StraightLineSurface: GlobalToLocal method without dynamic memory allocation This method...
bool contains(const std::string &s, const std::string ®x)
does a string contain the substring
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
const GenParticle * ConstGenParticlePtr
bool ignoreTruthLink(const T &p, bool vetoPileUp)
Helper function for SDO creation in PileUpTools.
double fractionalCharge(const T &p)
bool isBSM(const T &p)
APID: graviton and all Higgs extensions are BSM.
class which holds the full set of calibration constants for a given tube
float t0
< relative t0 in chamber (ns)
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