ATLAS Offline Software
Public Member Functions | Private Member Functions | Private Attributes | List of all members
MDTSensitiveDetector Class Reference

#include <MDTSensitiveDetector.h>

Inheritance diagram for MDTSensitiveDetector:
Collaboration diagram for MDTSensitiveDetector:

Public Member Functions

 MDTSensitiveDetector (const std::string &name, const std::string &hitCollectionName, const unsigned int nTubesMax)
 construction/destruction More...
 
 ~MDTSensitiveDetector ()=default
 
void Initialize (G4HCofThisEvent *HCE) override final
 member functions More...
 
G4bool ProcessHits (G4Step *aStep, G4TouchableHistory *ROhist) override final
 

Private Member Functions

 FRIEND_TEST (MDTSensitiveDetectortest, Initialize)
 
 FRIEND_TEST (MDTSensitiveDetectortest, ProcessHits)
 
 FRIEND_TEST (MDTSensitiveDetectortest, GetIdentifier)
 
int GetIdentifier (const G4TouchableHistory *touchHist)
 

Private Attributes

SG::WriteHandle< MDTSimHitCollectionm_MDTHitColl
 member data More...
 
const MdtHitIdHelperm_muonHelper
 
double m_driftRadius
 
double m_globalTime
 
Amg::Vector3D m_localPosition
 
double m_DEFAULT_TUBE_RADIUS
 radius assigned to radius if radius is invalid More...
 

Detailed Description

Author
danie.nosp@m.la.r.nosp@m.ebuzz.nosp@m.i@pv.nosp@m..infn.nosp@m..it
nveld.nosp@m.ik@n.nosp@m.ikhef.nosp@m..nl

Class methods and properties

The method MDTSensitiveDetector::ProcessHits is executed by the G4 kernel each time a charged particle (or a geantino) crosses one of the MDT Sensitive Gas volumes.

Once a G4Step is perfomed by the particle in the sensitive volume (both when the particle leaves the tube or stops in it), Pre and PostStepPositions are tranformed into local coordinates (chamber reference system, with Z along the tube direction and XY tranversal plane) and used to calculate the local direction of the track.

Two cases are given: 1) the particle over-passed the wire: here the drift radius (the impact parameter) is computed as the local direction distance from the wire;
2) the step doesn't allow the particle to over-pass the wire: here the shortest distance to the wire, which is one of the two end-points, is calculated for each step which occurs inside the sensitive volumes and only the closer one is kept; this case includes also the hard scattering case inside the sensitive volume.

Navigating with the touchableHistory method GetHistoryDepth() through the hierarchy of the volumes crossed by the particles, the MDTSensitiveDetector determinates the correct set of geometry parameters to be folded in the Simulation Identifier associated to each hit. The MDT SimIDs are 32-bit unsigned integers, built using the MuonSimEvent/MdtHitIdHelper class which inherits from the MuonHitIdHelper base class.

We describe in the following, how each field of the identifier is retrieved.

1) stationName, stationEta, stationPhi: when a volume is found in the hierarchy, whose name contains the substring "station", the stationName is extracted from the volume's name; stationPhi and stationEta are calculated starting from the volume copy number, assigned by MuonGeoModel.

2) multilayer: when a volume is found in the hierarchy, whose name contains the substring "component", the multilayer is set to 1 or to 2, according to the component number (multilayer=1 if the component is 1, 5 or 8; multilayer=2 if the component is 3, 7, 8, 10, 11 or 14).

3) tubeLayer and tube: when a volume is found in the hierarchy, whose name contains the substring "Drift", tubeLayer and tube are calculated starting from the Drift volume copy number.

notes:

1) this implementation of the MDT Sensitive Detectors can handle different situations: hard scattering of the muon on the sensitive volume (its direction changes), soft secondary particles completely included in the sensitive volume, muon hits masked by secondaries, like delta rays.

2) for each hit, the time of flight (the G4 globalTime), is recorded and associated to the hit.

3) more than none MDT hit can occur in the same tube. The hit selection is done at the level of the digitization procedure.

4) the MDTHit object contains: the SimID, the drift radius and the globalTime.

Definition at line 84 of file MDTSensitiveDetector.h.

Constructor & Destructor Documentation

◆ MDTSensitiveDetector()

MDTSensitiveDetector::MDTSensitiveDetector ( const std::string &  name,
const std::string &  hitCollectionName,
const unsigned int  nTubesMax 
)

construction/destruction

Definition at line 22 of file MDTSensitiveDetector.cxx.

23  : G4VSensitiveDetector( name )
24  , m_MDTHitColl( hitCollectionName )
25  , m_driftRadius(0.)
26  , m_globalTime(0.)
28 {
30 }

◆ ~MDTSensitiveDetector()

MDTSensitiveDetector::~MDTSensitiveDetector ( )
default

Member Function Documentation

◆ FRIEND_TEST() [1/3]

MDTSensitiveDetector::FRIEND_TEST ( MDTSensitiveDetectortest  ,
GetIdentifier   
)
private

◆ FRIEND_TEST() [2/3]

MDTSensitiveDetector::FRIEND_TEST ( MDTSensitiveDetectortest  ,
Initialize   
)
private

◆ FRIEND_TEST() [3/3]

MDTSensitiveDetector::FRIEND_TEST ( MDTSensitiveDetectortest  ,
ProcessHits   
)
private

◆ GetIdentifier()

int MDTSensitiveDetector::GetIdentifier ( const G4TouchableHistory *  touchHist)
private

Definition at line 132 of file MDTSensitiveDetector.cxx.

133 {
134  // attributes of the MDT identifier construction
135  std::string stationName;
136  int stationEta=1;
137  int stationPhi=1;
138  int multilayer=1;
139  int tubeLayer=1;
140  int tube=1;
141 
142  bool isAssembly = false;
143  // scan geometry tree to identify the tube
144  for (int i = touchHist->GetHistoryDepth(); i>=0; i--) {
145 
146  std::string::size_type npos;
147  std::string::size_type loc1;
148  std::string::size_type loc2;
149  std::string volName = touchHist->GetVolume(i)->GetName();
150 
151  // check if this station is an assembly
152  if ((npos = volName.find("av_")) != std::string::npos &&
153  (npos = volName.find("impr_")) != std::string::npos) isAssembly = true;
154 
155  // station: name, eta and phi (-> chamber!)
156  if ((npos = volName.find("station")) != std::string::npos && (!isAssembly)) {
157 
158  volName.resize(npos-2);
159  int volCopyNo = touchHist->GetVolume(i)->GetCopyNo();
160  volCopyNo=volCopyNo%1000;
161  stationName = volName;
162  stationEta = volCopyNo/100;
163  stationPhi = abs(volCopyNo%100);
164 
165  }
166  else if ((npos = volName.find("component")) != std::string::npos && (!isAssembly)) { // multilayer
167 
168  int gmID = 0;
169  if ((loc1 = volName.find('[')) != std::string::npos) {
170  if ((loc2 = volName.find(']', loc1+1)) != std::string::npos) {
171  std::istringstream istrvar(volName.substr(loc1+1,loc2-loc1-1));
172  istrvar>>gmID;
173  }
174  }
175  multilayer = gmID;
176 
177  } else if ((npos = volName.find("MDT")) != std::string::npos && isAssembly) {
178 
179  // vol name for Assembly components are
180  // av_WWW_impr_XXX_Muon::BMSxMDTxx_pv_ZZZ_NAME
181  // where WWW is ass. istance nr.
182  // XXX is comp. imprint nr.
183  // BMSxMDTxx is the name of the comp. log.Vol.
184  // x station sub-type; xx technology subtype
185  // ZZZ is the comp. number of order
186  // NAME is the comp. tag (geoIdentifierTag)
187  // for MDTs NAME is ml[1] or ml[2]
188  // copy numbers for Ass.components are =
189  // CopyNoBase(= geoIdentifierTag of the assembly) + geoIdentifierTag of the component
190  // geoIdentifierTag of the component = Job
191  // geoIdentifierTag of the assembly = (sideC*10000 +
192  // mirsign*1000 + abs(zi)*100 + fi+1)*100000;
193  // mirsign*1000 + abs(zi)*100 + fi+1)*100000;
194  //
195  if ((loc1 = volName.find("Muon::")) != std::string::npos) {
196  stationName = volName.substr(loc1+6,3);
197  }
198 
199  int copyNr = touchHist->GetVolume(i)->GetCopyNo();
200  int copyNrBase = int(copyNr/100000);
201  int sideC = int(copyNrBase/10000);
202  int zi = int((copyNrBase%1000)/100);
203  int fi = int(copyNrBase%100);
204  if (sideC == 1) zi = -zi;
205  stationEta = zi;
206  stationPhi = fi;
207 
208  int gmID = 0;
209  if ((loc1 = volName.find('[')) != std::string::npos) {
210  if ((loc2 = volName.find(']', loc1+1)) != std::string::npos) {
211  std::istringstream istrvar(volName.substr(loc1+1,loc2-loc1-1));
212  istrvar>>gmID;
213  }
214  }
215  multilayer = gmID;
216  } else if ((npos = volName.find("Drift")) != std::string::npos) { // layer and tube
217  tubeLayer = touchHist->GetVolume(i)->GetCopyNo()/maxNTubesPerLayer;
218  tube = touchHist->GetVolume(i)->GetCopyNo()%maxNTubesPerLayer;
219  }
220  }
221  //construct the hit identifier
222  return m_muonHelper->BuildMdtHitId(stationName, stationPhi, stationEta, multilayer,tubeLayer, tube);
223 }

◆ Initialize()

void MDTSensitiveDetector::Initialize ( G4HCofThisEvent *  HCE)
finaloverride

member functions

Definition at line 33 of file MDTSensitiveDetector.cxx.

34 {
35  if (!m_MDTHitColl.isValid()) m_MDTHitColl = std::make_unique<MDTSimHitCollection>();
37 }

◆ ProcessHits()

G4bool MDTSensitiveDetector::ProcessHits ( G4Step *  aStep,
G4TouchableHistory *  ROhist 
)
finaloverride

Definition at line 39 of file MDTSensitiveDetector.cxx.

39  {
40  G4Track* currentTrack = aStep->GetTrack();
41 
42  // MDTs sensitive to charged particle only
43  if (currentTrack->GetDefinition()->GetPDGCharge() == 0.0) {
44  if (currentTrack->GetDefinition()!=G4Geantino::GeantinoDefinition()) return true;
45  else if (currentTrack->GetDefinition()==G4ChargedGeantino::ChargedGeantinoDefinition()) return true;
46  }
47 
48  G4VPhysicalVolume* physVolPostStep = aStep->GetPostStepPoint()->GetPhysicalVolume();
49  if (nullptr == physVolPostStep) return true;
50 
51  // hit information to be recorded
52  double globalTime;
53  double driftRadius;
54  Amg::Vector3D localPosition;
55  localPosition.setZero();
56 
57  // get top transformation
58  const G4AffineTransform trans = currentTrack->GetTouchable()->GetHistory()->GetTopTransform();
59 
60  // transform pre and post step positions to local positions
61 
62  Amg::Vector3D localVertex1( Amg::Hep3VectorToEigen( trans.TransformPoint(aStep->GetPreStepPoint()->GetPosition()) ) );
63  Amg::Vector3D localVertex2( Amg::Hep3VectorToEigen( trans.TransformPoint(aStep->GetPostStepPoint()->GetPosition()) ) );
64 
65  // calculate local direction from begin- and end-point of the step
66  Amg::Vector3D localDirection( (localVertex2 - localVertex1) ); // normalized
67  localDirection.z() = 0.; // look in xy-plane
68 
69  // See if particle passed wire by projecting begin- and end-point on the step direction
70  if( (localVertex2.dot(localDirection)) * (localVertex1.dot(localDirection)) < 0 ) { // particle passed wire
71 
72  // compute drift radius ( = impact parameter)
73  double Xpos = localVertex1[0];
74  double Ypos = localVertex1[1];
75  double Xdir = localDirection[0];
76  double Ydir = localDirection[1];
77 
78  double Alpha = -1*(Xpos*Xdir + Ypos*Ydir)/(Xdir*Xdir + Ydir*Ydir); // localPosition*localDirection
79 
80  localPosition = localVertex1 + Alpha*(localVertex2-localVertex1);
81  driftRadius = localPosition.perp();
82  globalTime = aStep->GetPreStepPoint()->GetGlobalTime(); // take pre step time
83 
84  }else{ // particle didn't pass wire, one of the end-points is the shortest distance to the wire
85 
86  // calculate which of the two end-points is closer to the wire
87  double dist1 = localVertex1.perp();
88  double dist2 = localVertex2.perp();
89  if( dist1 < dist2 ){ // first is closer
90  driftRadius = dist1;
91  localPosition = localVertex1;
92  globalTime = aStep->GetPreStepPoint()->GetGlobalTime();
93  }else{ // second is closer
94  driftRadius = dist2;
95  localPosition = localVertex2;
96  globalTime = aStep->GetPostStepPoint()->GetGlobalTime();
97  }
98  }
99 
100  if( driftRadius < m_driftRadius ){ // check if current step came closer to the wire than the previous ones
102  m_globalTime = globalTime;
103  m_localPosition = localPosition;
104  }
105 
106  // check if particle left tube or stopped in tube
107  G4String namePreStepMat = aStep->GetPreStepPoint()->GetMaterial()->GetName();
108  G4String namePostStepMat = aStep->GetPostStepPoint()->GetMaterial()->GetName();
109  G4String nameSD = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume()->GetSensitiveDetector()->GetName();
110  // G4int trackid = aStep->GetTrack()->GetTrackID();
111  // see if we were in the sensitive volume and left it, or the particle was killed
112  if( ((nameSD) && (namePreStepMat != namePostStepMat)) || (currentTrack->GetTrackStatus() == fStopAndKill)){
113 
114  // get identifier
115  const G4TouchableHistory* touchHist = static_cast<const G4TouchableHistory*>(aStep->GetPreStepPoint()->GetTouchable());
116  int MDTid = GetIdentifier(touchHist);
117 
118  TrackHelper trHelp(aStep->GetTrack());
119 
120  // construct new mdt hit
121  m_MDTHitColl->Emplace(MDTid, m_globalTime, m_driftRadius, m_localPosition, trHelp.GenerateParticleLink(),
122  aStep->GetStepLength(),
123  aStep->GetTotalEnergyDeposit(),
124  currentTrack->GetDefinition()->GetPDGEncoding(),
125  aStep->GetPreStepPoint()->GetKineticEnergy());
126 
127  m_driftRadius = m_DEFAULT_TUBE_RADIUS; // reset start value of driftRadius
128  }
129  return true;
130 }

Member Data Documentation

◆ m_DEFAULT_TUBE_RADIUS

double MDTSensitiveDetector::m_DEFAULT_TUBE_RADIUS
private

radius assigned to radius if radius is invalid

Definition at line 110 of file MDTSensitiveDetector.h.

◆ m_driftRadius

double MDTSensitiveDetector::m_driftRadius
private

Definition at line 105 of file MDTSensitiveDetector.h.

◆ m_globalTime

double MDTSensitiveDetector::m_globalTime
private

Definition at line 106 of file MDTSensitiveDetector.h.

◆ m_localPosition

Amg::Vector3D MDTSensitiveDetector::m_localPosition
private

Definition at line 107 of file MDTSensitiveDetector.h.

◆ m_MDTHitColl

SG::WriteHandle<MDTSimHitCollection> MDTSensitiveDetector::m_MDTHitColl
private

member data

Definition at line 102 of file MDTSensitiveDetector.h.

◆ m_muonHelper

const MdtHitIdHelper* MDTSensitiveDetector::m_muonHelper
private

Definition at line 103 of file MDTSensitiveDetector.h.


The documentation for this class was generated from the following files:
Muon::nsw::STGTPSegments::moduleIDBits::stationPhi
constexpr uint8_t stationPhi
station Phi 1 to 8
Definition: NSWSTGTPDecodeBitmaps.h:129
max
#define max(a, b)
Definition: cfImp.cxx:41
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
ZDC::sideC
BySideTypeMod sideC(-1)
dumpTgcDigiDeadChambers.stationName
dictionary stationName
Definition: dumpTgcDigiDeadChambers.py:30
MDTSensitiveDetector::m_muonHelper
const MdtHitIdHelper * m_muonHelper
Definition: MDTSensitiveDetector.h:103
MDTSensitiveDetector::m_DEFAULT_TUBE_RADIUS
double m_DEFAULT_TUBE_RADIUS
radius assigned to radius if radius is invalid
Definition: MDTSensitiveDetector.h:110
Trk::loc2
@ loc2
generic first and second local coordinate
Definition: ParamDefs.h:41
MdtHitIdHelper::GetHelper
static const MdtHitIdHelper * GetHelper(unsigned int nTubes=78)
Definition: MdtHitIdHelper.cxx:24
Amg::Hep3VectorToEigen
Amg::Vector3D Hep3VectorToEigen(const CLHEP::Hep3Vector &CLHEPvector)
Converts a CLHEP-based CLHEP::Hep3Vector into an Eigen-based Amg::Vector3D.
Definition: CLHEPtoEigenConverter.h:137
TrackHelper
Definition: TrackHelper.h:14
lumiFormat.i
int i
Definition: lumiFormat.py:92
Trk::driftRadius
@ driftRadius
trt, straws
Definition: ParamDefs.h:59
MDTSensitiveDetector::m_localPosition
Amg::Vector3D m_localPosition
Definition: MDTSensitiveDetector.h:107
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
MDTSensitiveDetector::m_MDTHitColl
SG::WriteHandle< MDTSimHitCollection > m_MDTHitColl
member data
Definition: MDTSensitiveDetector.h:102
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
checkFileSG.fi
fi
Definition: checkFileSG.py:65
MDTSensitiveDetector::GetIdentifier
int GetIdentifier(const G4TouchableHistory *touchHist)
Definition: MDTSensitiveDetector.cxx:132
Muon::nsw::STGTPSegments::moduleIDBits::stationEta
constexpr uint8_t stationEta
1 to 3
Definition: NSWSTGTPDecodeBitmaps.h:127
Trk::loc1
@ loc1
Definition: ParamDefs.h:40
calibdata.tube
tube
Definition: calibdata.py:31
MdtHitIdHelper::BuildMdtHitId
int BuildMdtHitId(const std::string &, const int, const int, const int, const int, const int) const
Definition: MdtHitIdHelper.cxx:95
MDTSensitiveDetector::m_driftRadius
double m_driftRadius
Definition: MDTSensitiveDetector.h:105
MDTSensitiveDetector::m_globalTime
double m_globalTime
Definition: MDTSensitiveDetector.h:106