ATLAS Offline Software
PixelSensorSD.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 //
6 // Pixel Sensitive Detector.
7 // The Hits are processed here. For every hit I get the position and
8 // an information on the sensor in which the interaction happened
9 //
10 
11 // Class header
12 #include "PixelSensorSD.h"
13 #include <GaudiKernel/EventContext.h>
14 
15 // Athena headers
17 #include "MCTruth/TrackHelper.h"
18 
19 // Geant4 headers
20 #include "G4ChargedGeantino.hh"
21 #include <G4EventManager.hh>
22 #include "G4Geantino.hh"
23 #include "G4SDManager.hh"
24 #include "G4Step.hh"
25 #include "G4ThreeVector.hh"
26 
27 // CLHEP headers
28 #include "CLHEP/Geometry/Transform3D.h"
29 #include "CLHEP/Units/SystemOfUnits.h"
30 
31 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
32 
33 PixelSensorSD::PixelSensorSD(const std::string& name, const std::string& hitCollectionName)
34  : G4VSensitiveDetector( name )
35  , m_HitCollName( hitCollectionName )
36 {
37 }
38 
39 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
40 // Initialize from G4 - cache the hit collection for the current event
41 void PixelSensorSD::Initialize(G4HCofThisEvent *)
42 {
43  // ISF calls G4SDManager::PrepareNewEvent() before the Geant4 event loop starts...
44  if(auto* eventManger = G4EventManager::GetEventManager()){
45  if(auto* eventInfo = static_cast<AtlasG4EventUserInfo*>(eventManger->GetUserInformation())){
46  m_HitColl = eventInfo->GetHitCollectionMap()->Find<SiHitCollection>(m_HitCollName);
47  }
48  }
49 }
50 
51 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
52 
53 G4bool PixelSensorSD::ProcessHits(G4Step* aStep, G4TouchableHistory* /*ROhist*/)
54 {
55  if (verboseLevel>5) G4cout << "Process Hit" << G4endl;
56 
57  G4double edep = aStep->GetTotalEnergyDeposit();
58  edep *= CLHEP::MeV;
59  if(edep==0.) {
60  if(aStep->GetTrack()->GetDefinition() != G4Geantino::GeantinoDefinition() &&
61  aStep->GetTrack()->GetDefinition() != G4ChargedGeantino::ChargedGeantinoDefinition())
62  return false;
63  }
64 
65  //use the global time. i.e. the time from the beginning of the event
66  //
67  // Get the Touchable History:
68  //
69  const G4TouchableHistory *myTouch = dynamic_cast<const G4TouchableHistory*>(aStep->GetPreStepPoint()->GetTouchable());
70  if (not myTouch) {
71  G4cout << "PixelSensorSD::ProcessHits bad dynamic_cast" << G4endl;
72  return false;
73  }
74  if(verboseLevel>5){
75  for (int i=0;i<myTouch->GetHistoryDepth();i++){
76  std::string detname=myTouch->GetVolume(i)->GetLogicalVolume()->GetName();
77  int copyno=myTouch->GetVolume(i)->GetCopyNo();
78  G4cout << "Volume " <<detname <<" Copy Nr. " << copyno << G4endl;
79  }
80  }
81  //
82  // Get the hit coordinates. Start and End Point
83  //
84  G4ThreeVector coord1 = aStep->GetPreStepPoint()->GetPosition();
85  G4ThreeVector coord2 = aStep->GetPostStepPoint()->GetPosition();
86 
87  // Calculate the local step begin and end position.
88  // From a G4 FAQ:
89  // http://geant4-hn.slac.stanford.edu:5090/HyperNews/public/get/geometry/17/1.html
90  //
91  const G4AffineTransform transformation = myTouch->GetHistory()->GetTopTransform();
92  G4ThreeVector localPosition1 = transformation.TransformPoint(coord1);
93  G4ThreeVector localPosition2 = transformation.TransformPoint(coord2);
94 
95  HepGeom::Point3D<double> lP1,lP2;
96  lP1[SiHit::xEta] = localPosition1[2]*CLHEP::mm;
97  lP1[SiHit::xPhi] = localPosition1[1]*CLHEP::mm;
98  lP1[SiHit::xDep] = localPosition1[0]*CLHEP::mm;
99 
100  lP2[SiHit::xEta] = localPosition2[2]*CLHEP::mm;
101  lP2[SiHit::xPhi] = localPosition2[1]*CLHEP::mm;
102  lP2[SiHit::xDep] = localPosition2[0]*CLHEP::mm;
103 
104  //
105  // Get it into a vector in local coords and with the right units:
106 
107 
108  // Now Navigate the history to know in what detector the step is:
109  // and finally set the ID of det element in which the hit is.
110  //
111  //G4int History;
112  //
113  // Is it TB, barrel or endcap?
114  //
115  int BrlEcap = 0;
116  int LayerDisk = 0;
117  int etaMod = 0;
118  int phiMod = 0;
119  int side = 0;
120 
121  // G4VPhysicalVolume* TheVolume = myTouch->GetVolume();
122  //
123  // In the case of the TB the positioning integers won't be initialized
124  // and the identifying integer will be zero. There is no need to do
125  // anything else
126 
127  int BEcopyNo = myTouch->GetVolume()->GetCopyNo();
128 
129  // Barrel
130  if(BEcopyNo == 100) {
131  // Move up of one level in the tree to get the module number:
132  //
133  etaMod = myTouch->GetVolume(1)->GetCopyNo();
134  //
135  // Another level for the ladder
136  //
137  phiMod = myTouch->GetVolume(2)->GetCopyNo();
138  //
139  // Another one for the layer
140  //
141  LayerDisk = myTouch->GetVolume(3)->GetCopyNo();
142  //
143  // Some printout
144  //
145  if (verboseLevel>5){
146  G4cout << "In the Pixel Barrel" << G4endl;
147  G4cout << "----- Phi Module # " << phiMod << G4endl;
148  G4cout << "----- Eta Ladder # " << etaMod << G4endl;
149  G4cout << "----- Layer # " << LayerDisk << G4endl;
150  }
151 
152  // Standard ATLAS EndCap
153  } else if (BEcopyNo == 200) {
154 
155  // Use the copy no. to get the id:
156  phiMod = myTouch->GetVolume(1)->GetCopyNo();
157  if (phiMod == 48) phiMod = 0;
158 
159  // etaMod always 0.
160 
161  // Move up of one level in the tree to get the disk number:
162  LayerDisk = myTouch->GetVolume(2)->GetCopyNo();
163 
164  // Move up of one level in the tree to get the EC number:
165  BrlEcap = myTouch->GetVolume(3)->GetCopyNo();
166  //The following is no longer necessary
167  //if(BrlEcap == -2) BrlEcap = 1;
168 
169  // Workaround for bug in cosmic setup
170  if (BrlEcap == 0) {
171  BrlEcap = (coord1.z() > 0) ? 2 : -2;
172  }
173 
174  // Some printout
175  if (verboseLevel>5){
176  G4cout << "In the Pixel EndCap" << G4endl;
177  G4cout << "----- PhiModule # " << phiMod << G4endl;
178  G4cout << "----- Disk # " << LayerDisk << G4endl;
179  G4cout << "----- Endcap # " << BrlEcap << G4endl;
180  }
181 
182  // SLHC EndCap
183  } else if (BEcopyNo == 300) {
184 
185  // Use the copy no. to get the id:
186  phiMod = myTouch->GetVolume(1)->GetCopyNo();
187 
188  // Note: copyNo is 2*ieta for front face, 2*ieta+1 for back face
189  etaMod = myTouch->GetVolume(2)->GetCopyNo()/2;
190 
191  // Move up of one level in the tree to get the disk number:
192  LayerDisk = myTouch->GetVolume(3)->GetCopyNo();
193 
194  // Move up of one level in the tree to get the EC number:
195  BrlEcap = myTouch->GetVolume(4)->GetCopyNo();
196  //if(BrlEcap == -2) BrlEcap = 1;
197 
198  // Some printout
199  if (verboseLevel>5){
200  G4cout << "In the SLHC Pixel EndCap" << G4endl;
201  G4cout << "----- PhiModule # " << phiMod << G4endl;
202  G4cout << "----- Ring/Eta # " << etaMod << G4endl;
203  G4cout << "----- Disk # " << LayerDisk << G4endl;
204  G4cout << "----- Endcap # " << BrlEcap << G4endl;
205  }
206 
207  } else if(BEcopyNo == 400) { //DBM
208 
209  // Note: there is one volume (3-layers unit) contain the diamond+chip volume
210  // so one increment is needed after 'layerDisk'
211 
212  // only one eta module for the DBM
213  etaMod = 0;
214 
215  // Move up one level to get the layer number, 3 layers per telescope
216  LayerDisk = myTouch->GetVolume(1)->GetCopyNo();
217 
218  // Move up two level to get the phi module, azimuthal position of telescope
219  phiMod = myTouch->GetVolume(3)->GetCopyNo();
220 
221  // Move up one level to get the DBM side, A side or C side
222  BrlEcap = myTouch->GetVolume(4)->GetCopyNo();
223 
224  // Some printout
225  if (verboseLevel>5){
226  G4cout << "In the DBM" << G4endl;
227  G4cout << "----- PhiModule # " << phiMod << G4endl;
228  G4cout << "----- Ring/Eta # " << etaMod << G4endl;
229  G4cout << "----- Disk # " << LayerDisk << G4endl;
230  G4cout << "----- Endcap # " << BrlEcap << G4endl;
231  }
232 
233  } else if(BEcopyNo == 500) { //Inclined
234 
235  std::string volName = myTouch->GetVolume()->GetName();
236 
237  // split the volname vs '_'
238  std::replace(volName.begin(),volName.end(),'_',' ');
239 
240  std::vector<std::string> v;
241  std::istringstream s(volName);
242  std::string tmp;
243  while (s >> tmp) {
244  v.push_back(tmp);
245  }
246 
247  BrlEcap = 0; // no endcap defined in alpine
248  LayerDisk = atoi(v[1].c_str());
249  phiMod = atoi(v[2].c_str());
250  etaMod = atoi(v[3].c_str());
251 
252  if (verboseLevel>5){
253  G4cout << "Volume name " << volName <<G4endl;
254  double xpos = coord1.x();
255  double ypos = coord1.y();
256  double zpos = coord1.z();
257  double r = sqrt(xpos*xpos+ypos*ypos);
258  G4cout << "In the Alpine " << G4endl;
259  G4cout << "----- PhiModule # " << phiMod << G4endl;
260  G4cout << "----- Ring/Eta # " << etaMod << G4endl;
261  G4cout << "----- Disk # " << LayerDisk << G4endl;
262  G4cout << "----- Endcap # " << BrlEcap << G4endl;
263  G4cout << "----- Pos # " << r<<" "<<zpos << G4endl;
264  G4cout << "----- volume " << myTouch->GetVolume()->GetName()<< G4endl;
265  G4cout << " " << myTouch->GetVolume(1)->GetName()<<" "<<
266  myTouch->GetVolume(2)->GetName()<< " " << myTouch->GetVolume(3)->GetName()<<G4endl;
267  }
268 
269  } else if(BEcopyNo == 600) { //ITk ECring
270 
271  std::string volName = myTouch->GetVolume()->GetName();
272 
273  // split the volname vs '_'
274  std::replace(volName.begin(),volName.end(),'_',' ');
275 
276  std::vector<std::string> v;
277  std::istringstream s(volName);
278  std::string tmp;
279  while (s >> tmp) {
280  v.push_back(tmp);
281  }
282 
283  BrlEcap = atoi(v[1].c_str());
284  LayerDisk = atoi(v[2].c_str());
285  phiMod = atoi(v[3].c_str());
286  etaMod = atoi(v[4].c_str());
287 
288  if (verboseLevel>5){
289  double xpos = coord1.x();
290  double ypos = coord1.y();
291  double zpos = coord1.z();
292  double r = sqrt(xpos*xpos+ypos*ypos);
293  G4cout << "Volume name " << volName <<G4endl;
294  G4cout << "In the ITk EC ring " << G4endl;
295  G4cout << "----- PhiModule # " << phiMod << G4endl;
296  G4cout << "----- Ring/Eta # " << etaMod << G4endl;
297  G4cout << "----- Disk # " << LayerDisk << G4endl;
298  G4cout << "----- Endcap # " << BrlEcap << G4endl;
299  G4cout << "----- Pos # " << r<<" "<<zpos << G4endl;
300  G4cout << "----- volume " << myTouch->GetVolume()->GetName()<< G4endl;
301  G4cout << " " << myTouch->GetVolume(1)->GetName()<<" "<<
302  myTouch->GetVolume(2)->GetName()<< " " << myTouch->GetVolume(3)->GetName()<<G4endl;
303  }
304  }
305  else {
306  // Do not expect other numbers. Need to fix PixelGeoModel if this occurs.
307  G4ExceptionDescription description;
308  description << "ProcessHits: Unrecognized geometry in Pixel sensitive detector. Please contact the maintainer of the Pixel Detector Description.";
309  description << "If you are processing a GeoModelXML geometry, please ensure a PixelSensorGmxSD instance is used instead of this (PixelSensorSD).";
310  G4Exception("PixelSensorSD", "UnrecognizedPixelGeometry", FatalException, description);
311  abort();
312  }
313 
314  // get the HepMcParticleLink from the TrackHelper
315 
316  TrackHelper trHelp(aStep->GetTrack());
317  // Temporary solution to get EventContext from a Geant4 thread
318  EventContext const* eventContext{nullptr};
319  if(auto* eventInfo = AtlasG4EventUserInfo::GetEventUserInfo()){
320  eventContext = &eventInfo->GetEventContext();
321  }
322 
323  m_HitColl->Emplace(lP1,
324  lP2,
325  edep,
326  aStep->GetPreStepPoint()->GetGlobalTime(),
327  eventContext ? trHelp.GenerateParticleLink(*eventContext) : trHelp.GenerateParticleLink(),
328  0,BrlEcap,LayerDisk,etaMod,phiMod,side);
329  return true;
330 }
AtlasG4EventUserInfo::GetEventUserInfo
static AtlasG4EventUserInfo * GetEventUserInfo()
Definition: AtlasG4EventUserInfo.h:125
SiHit::xPhi
@ xPhi
Definition: SiHit.h:162
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:310
beamspotman.r
def r
Definition: beamspotman.py:672
AtlasG4EventUserInfo
This class is attached to G4Event objects as UserInformation. It holds a pointer to the HepMC::GenEve...
Definition: AtlasG4EventUserInfo.h:27
python.SystemOfUnits.mm
float mm
Definition: SystemOfUnits.py:98
TrackHelper.h
AtlasHitsVector< SiHit >
PixelSensorSD::PixelSensorSD
PixelSensorSD(const std::string &name, const std::string &hitCollectionName)
Definition: PixelSensorSD.cxx:33
PixelSensorSD::Initialize
void Initialize(G4HCofThisEvent *) override final
Definition: PixelSensorSD.cxx:41
PixelSensorSD::m_HitCollName
std::string m_HitCollName
Definition: PixelSensorSD.h:47
python.SystemOfUnits.MeV
float MeV
Definition: SystemOfUnits.py:172
TRT::Hit::side
@ side
Definition: HitInfo.h:83
PixelSensorSD::m_HitColl
SiHitCollection * m_HitColl
Definition: PixelSensorSD.h:48
AtlasHitsVector::Emplace
void Emplace(Args &&... args)
Definition: AtlasHitsVector.h:80
TrackHelper
Definition: TrackHelper.h:16
LayerDisk
Definition: WaferTree.h:57
lumiFormat.i
int i
Definition: lumiFormat.py:85
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
PixelSensorSD.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
SiHit::xDep
@ xDep
Definition: SiHit.h:162
SiHit::xEta
@ xEta
Definition: SiHit.h:162
python.PyAthena.v
v
Definition: PyAthena.py:154
PixelSensorSD::ProcessHits
G4bool ProcessHits(G4Step *, G4TouchableHistory *) override final
Definition: PixelSensorSD.cxx:53
AtlasG4EventUserInfo.h
python.SystemOfUnits.s
float s
Definition: SystemOfUnits.py:147
CxxUtils::atoi
int atoi(std::string_view str)
Helper functions to unpack numbers decoded in string into integers and doubles The strings are requir...
Definition: Control/CxxUtils/Root/StringUtils.cxx:85
TrackHelper::GenerateParticleLink
HepMcParticleLink GenerateParticleLink()
Generates a creates new HepMcParticleLink object on the stack based on GetUniqueID(),...
Definition: TrackHelper.h:50
fillSCTHists.etaMod
etaMod
Definition: fillSCTHists.py:23
description
std::string description
glabal timer - how long have I taken so far?
Definition: hcg.cxx:91