ATLAS Offline Software
RPCSensitiveDetectorCosmics.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 #include "G4ThreeVector.hh"
7 #include "G4Trd.hh"
9 #include <string>
10 #include "G4Geantino.hh"
11 #include "G4ChargedGeantino.hh"
12 
13 //#include "SimHelpers/DetectorGeometryHelper.h"
14 #include "MCTruth/TrackHelper.h"
15 
17 
18 // construction/destruction
19 RPCSensitiveDetectorCosmics::RPCSensitiveDetectorCosmics(const std::string& name, const std::string& hitCollectionName, unsigned int nGasGaps)
20  : G4VSensitiveDetector( name )
21  , m_myRPCHitColl( hitCollectionName )
22  , m_globalTime(0.)
23  , m_isGeoModel(true)
24  , m_momMag(0.)
25 {
27 }
28 
30 {
31  if (!m_myRPCHitColl.isValid()) m_myRPCHitColl = std::make_unique<RPCSimHitCollection>();
32  if (verboseLevel>1) G4cout << "Initializing SD" << G4endl;
33  // FIXME this next bit probebly only needs to be done once pre job
34  // rather than once per G4Event?
35 /* DetectorGeometryHelper DGHelp;
36  if( DGHelp.GeometryType("Muon") == GeoModel ){
37  m_isGeoModel = true;
38  if (verboseLevel>1) G4cout << "Muon Geometry is from GeoModel" << G4endl;
39  } else {
40  m_isGeoModel = false;
41  if (verboseLevel>1) G4cout << "Muon Geometry is from pure G4" << G4endl;
42  }*/
43  m_mom = Amg::Vector3D(0.,0.,0.);
44  m_globH = Amg::Vector3D(0.,0.,0.);
45 }
46 
47 G4bool RPCSensitiveDetectorCosmics::ProcessHits(G4Step* aStep,G4TouchableHistory*) {
48  G4Track* currentTrack = aStep->GetTrack();
49 
50  if (currentTrack->GetDefinition()->GetPDGCharge() == 0.0) {
51  if (currentTrack->GetDefinition()!=G4Geantino::GeantinoDefinition()) return true;
52  // else if (currentTrack->GetDefinition()==G4ChargedGeantino::ChargedGeantinoDefinition()) return true;
53  }
54 
55  const G4TouchableHistory* touchHist = static_cast<const G4TouchableHistory*>(aStep->GetPreStepPoint()->GetTouchable());
56  G4ThreeVector position = aStep->GetPreStepPoint()->GetPosition();
57  G4ThreeVector postPosition = aStep->GetPostStepPoint()->GetPosition();
58  const G4AffineTransform trans = currentTrack->GetTouchable()->GetHistory()->GetTopTransform(); // from global to local
59 
60  // necessary to assign correct identifiers
61  int rpcIsRotated = 0;
62  // int layer = 0;
63 
64  std::string tech;
65  // fields for the RPC identifier construction
66  std::string stationName;
67  int stationEta= 0;
68  int stationPhi= 0;
69  int doubletR= 0;
70  int doubletZ= 0;
71  int doubletPhi= 0;
72  int gasGap= 0;
73  // int eta_inversed=0;
74  // int phi_inversed=0;
75  int station_rotated=0; // tells us if the station was rotated before being positioned.
76  // if =1 we have to correct some IDs
77  int zNeg_original=0; // tells if the station at z<0 was obtained duplicating a station at z>0
78 
79  // RPC hit information
80  double globalTime = aStep->GetPreStepPoint()->GetGlobalTime();
81  Amg::Vector3D localPosition = Amg::Hep3VectorToEigen( trans.TransformPoint(position) );
82  Amg::Vector3D localPostPosition = Amg::Hep3VectorToEigen( trans.TransformPoint(postPosition) );
83 
84  // global coordinates
85  G4ThreeVector globVrtx = aStep->GetPreStepPoint()->GetPosition();
86 
87  // distance of the hit from (0,0,0) vertex - calculated from the PreStepPoint (approximation)
88  // double dist = globVrtx.mag();
89  double lightspeed = 299.792458; /* in vacuo speed of light [mm/ns] */
90  // double tOrigin = dist / lightspeed;
91 
92  G4int trackid = aStep->GetTrack()->GetTrackID();
93  m_currVertex = Amg::Hep3VectorToEigen( aStep->GetTrack()->GetVertexPosition() );
94 
95  // for cosmics: only primary muon tracks - track momentum when first entering the spectrometer (one muon per event)
96  if ((m_currVertex != m_vertex) && (trackid == 1)) {
97  // after calculationg the momentum magnidude, normalize it
98  m_mom = Amg::Hep3VectorToEigen( currentTrack->GetMomentum() );
99  m_momMag = m_mom.mag();
100  m_mom.normalize();
101  // the direction of the primary mu is used to calculate the t0, the position ot the t0, m_globH, is ONE for a track
102  Amg::Vector3D globVrtxFix = Amg::Hep3VectorToEigen( globVrtx );
103  double AlphaGlobal = -1*(globVrtxFix[0]*m_mom[0] + globVrtxFix[1]*m_mom[1] + globVrtxFix[2]*m_mom[2])/(m_mom[0]*m_mom[0] + m_mom[1]*m_mom[1] + m_mom[2]*m_mom[2]);
104  m_globH = globVrtxFix + AlphaGlobal*m_mom;
105  }
106  double globalDist = sqrt((m_globH[0] - globVrtx[0])*(m_globH[0] - globVrtx[0]) +
107  (m_globH[1] - globVrtx[1])*(m_globH[1] - globVrtx[1]) +
108  (m_globH[2] - globVrtx[2])*(m_globH[2] - globVrtx[2]));
109  double tof = globalDist / lightspeed;
110 
111  int mydbZ=0;
112  int mydbPMod=0;
113  int mydbP=0;
114  bool isAssembly = false;
115  // scan geometry tree to identify the hit channel
116  for (int i=touchHist->GetHistoryDepth();i>=0;i--) {
117 
118  std::string::size_type npos;
119  std::string volName = touchHist->GetVolume(i)->GetName();
120  std::string num=volName.substr(3,2);
121  if(num[0]==' ') num[0]=0;
122 
123  // check if this station is an assembly
124  if ((npos = volName.find("av_")) != std::string::npos &&
125  (npos = volName.find("impr_")) != std::string::npos) isAssembly = true;
126 
127  // stationName, stationEta, stationPhi
128  if ((npos = volName.find("station")) != std::string::npos && (!isAssembly)) {
129 
130  stationName = volName.substr(0,npos-1);
131 
132  int volCopyNo = touchHist->GetVolume(i)->GetCopyNo();
133 
134  if(abs(volCopyNo/1000)==1){
135  zNeg_original=1;
136  volCopyNo=volCopyNo%1000;
137  }
138 
139  stationEta = volCopyNo/100;
140  stationPhi = abs(volCopyNo%100);
141 
142  if(stationEta<0&&!zNeg_original) station_rotated=1;
143 
144  // stationName, stationEta, stationPhi
145  } else if ((npos = volName.find("RPC")) != std::string::npos && isAssembly) {
146  // vol name for Assembly components are
147  // av_WWW_impr_XXX_Muon::BMSxMDTxx_pv_ZZZ_NAME
148  // where WWW is ass. istance nr.
149  // XXX is comp. imprint nr.
150  // BMSxMDTxx is the name of the comp. log.Vol.
151  // x station sub-type; xx technology subtype
152  // ZZZ is the comp. number of order
153  // NAME is the comp. tag (geoIdentifierTag)
154  // for RPCs it is SwapdbPdbRdbZ[aaa]
155  // with aaa = doubletZ + doubletR*100 + dbphi*1000;
156  // aaa = -aaa if iswap == -1
157  // dbphi = 1 always but for S1 or S2 at doubletPhi = 2
158  // copy numbers for Ass.components are =
159  // CopyNoBase(= geoIdentifierTag of the assembly) + geoIdentifierTag of the component
160  // geoIdentifierTag of the component = Job
161  // geoIdentifierTag of the assembly = (sideC*10000 +
162  // mirsign*1000 + abs(zi)*100 + fi+1)*100000;
163  // mirsign = 1 if zi<0 and !mirrored; otherwise 0
164  std::string::size_type loc1,loc2;
165  if ((loc1 = volName.find("Muon::")) != std::string::npos) {
166  stationName = volName.substr(loc1+6,4); //type and subtype
167  }
168 
169  int volCopyNo = touchHist->GetVolume(i)->GetCopyNo();
170  int copyNrBase = int(volCopyNo/100000);
171  int sideC = int(copyNrBase/10000);
172  int zi = int((copyNrBase%1000)/100);
173  int mirfl = int((copyNrBase%10000)/1000);
174  int fi = int(copyNrBase%100);
175  if (sideC == 1) zi = -zi;
176  stationEta = zi;
177  stationPhi = fi;
178  zNeg_original = mirfl;
179 
180  if(stationEta<0&&!zNeg_original) station_rotated=1;
181  tech=volName.substr(npos,5);
182 
183  // now get the geoIdentifierTag of the rpc components
184  int gmID = 0;
185  if ((loc1 = volName.find('[')) != std::string::npos) {
186  if ((loc2 = volName.find(']', loc1+1)) != std::string::npos) {
187  std::istringstream istrvar(volName.substr(loc1+1,loc2-loc1-1));
188  istrvar>>gmID;
189  }
190  }
191  int kk=gmID;
192 
193  if (kk < 0) rpcIsRotated=1;
194 
195  doubletR =(abs(kk)%1000)/100;
196  mydbZ = abs(int(kk%10));
197  mydbPMod = abs(int(kk/1000));
198  // doubleR, doubletZ
199  } else if ((npos = volName.find("rpccomponent")) != std::string::npos && (!isAssembly)) {
200 
201  tech=volName.substr(npos-5,5);
202 
203  std::string::size_type loc1,loc2;
204  int gmID = 0;
205  if ((loc1 = volName.find('[')) != std::string::npos) {
206  if ((loc2 = volName.find(']', loc1+1)) != std::string::npos) {
207  std::istringstream istrvar(volName.substr(loc1+1,loc2-loc1-1));
208  istrvar>>gmID;
209  }
210  }
211  mydbZ = abs(int(gmID%10));
212  mydbPMod = abs(int(gmID/1000));
213 
214  int kk=touchHist->GetVolume(i)->GetCopyNo();
215 
216  if (kk < 0) rpcIsRotated=1;
217 
218  doubletR=(abs(kk)%1000)/100;
219 
220  // doubleR
221  } else if ((npos = volName.find("rpccomponent")) != std::string::npos && (!isAssembly)) {
222 
223  std::string::size_type loc1,loc2;
224  int gmID = 0;
225  if ((loc1 = volName.find('[')) != std::string::npos) {
226  if ((loc2 = volName.find(']', loc1+1)) != std::string::npos) {
227  std::istringstream istrvar(volName.substr(loc1+1,loc2-loc1-1));
228  istrvar>>gmID;
229  }
230  }
231  mydbZ = abs(int(gmID%10));
232  mydbPMod = abs(int(gmID/1000));
233 
234  int kk=touchHist->GetVolume(i)->GetCopyNo();
235 
236  if (kk < 0) rpcIsRotated=1;
237 
238  doubletR=(abs(kk)%1000)/100;
239 
240  // gasGap
241  } else if ((npos = volName.find("layer")) != std::string::npos) {
242 
243  int copyNo = touchHist->GetVolume(i)->GetCopyNo();
244 
245  if (copyNo == 1) {
246  rpcIsRotated ? gasGap = 2 : gasGap = 1;
247  } else if (copyNo ==2) {
248  rpcIsRotated ? gasGap = 1 : gasGap = 2;
249  }
250 
251  // doubletPhi
252  } else if((npos = volName.find("gas volume")) != std::string::npos) {
253 
254  int copyNo = touchHist->GetVolume(i)->GetCopyNo();
255  if (copyNo == 0) {
256  doubletPhi = 1;
257  } else if (copyNo == 10) {
258  doubletPhi = 2;
259  }
260  mydbP = doubletPhi;
261  int ngap_in_s=0;
262  int nstrippanel_in_s=0;
263  std::string::size_type loc1;
264  if ((loc1 = volName.find("gg_in_s")) != std::string::npos) {
265  std::istringstream istrvar(volName.substr(loc1-1,1));
266  istrvar>>ngap_in_s;
267  }
268  if ((loc1 = volName.find("sp_in_s")) != std::string::npos) {
269  std::istringstream istrvar(volName.substr(loc1-1,1));
270  istrvar>>nstrippanel_in_s;
271  }
272  if (ngap_in_s == 1 && nstrippanel_in_s == 2){
273  if(localPosition.y()>0) mydbP=2;
274  else mydbP=1;
275  } else if (ngap_in_s == 1 && nstrippanel_in_s == 1){
276  mydbP = mydbPMod;
277  }
278  }
279  }
280 
282  // correct wrong IDs due to station rotation. only doubletZ and doubletPhi are affected at this point
284 
285  if(station_rotated){
286  // doubletPhi correction
287  // note that this is correct also for ribs chambers
288  mydbP++;
289  if (mydbP>2) mydbP=1;
290  // doubletZ correction: specialStations have already been correted
291  // the others do not need any correction, because doubletZ increases with |Z|, thus not
292  // changing in the rotation
293 
294  // strip numbering: if the station is rotated both eta and phi directions get inversed.
295  // commented out for geomodel!
296 
297  if(!m_isGeoModel){
298  localPosition.z() = -localPosition.z();
299  localPosition.y() = -localPosition.y();
300  localPostPosition.z() = -localPostPosition.z();
301  localPostPosition.y() = -localPostPosition.y();
302  }
303  }
304 
305  // further correction on the eta direction due to rpc component rotation
306  // commented for geomodel!
307  if(!rpcIsRotated&&!m_isGeoModel) {
308  localPosition.z() = -localPosition.z();
309  localPostPosition.z() = -localPostPosition.z();
310  }
311 
313 
314  // now we have the position in the gas gap, with correct axis orientation, and the offlineIDs *of the strip panel*
315  // nstrip is supposed to be calculated by RPC_Digitizer.
316 
317  // construct two (one in eta and one in phi) new RPC hits and store them in hit collection
318 
319  //construct the hit identifiers
320 
321  if (verboseLevel>1) {
322  G4cout << "hit in station "<<stationName<< " on technology "<<tech << G4endl;
323  G4cout << "constructing ids (stName, stEta, stPhi, dr, dZ, dPhi)= "<<stationName<< " "<< stationEta<<" " << stationPhi<< " "<<doubletR<< " "<< doubletZ<< " "<<doubletPhi << G4endl;
324  }
325 
327  mydbZ, doubletR, gasGap, mydbP,0);
328 
330  mydbZ, doubletR, gasGap, mydbP,1);
331 
332  // retrieve track barcode
333  TrackHelper trHelp(aStep->GetTrack());
334 
335  //construct new rpc hit
336  m_vertex = Amg::Hep3VectorToEigen( aStep->GetTrack()->GetVertexPosition() );
337 
338  // if the track m_vertex is far from (0,0,0), takes the tof, otherwise take the "usual" g4 globalTime
339  (((m_vertex.mag()) < 100) ? (m_globalTime = globalTime) : (m_globalTime = tof));
340 
341  m_myRPCHitColl->Emplace(RPCid_eta, m_globalTime,
342  localPosition, trHelp.GenerateParticleLink(), localPostPosition,
343  aStep->GetTotalEnergyDeposit(),
344  aStep->GetStepLength(),
345  currentTrack->GetDefinition()->GetPDGEncoding(),
346  aStep->GetPreStepPoint()->GetKineticEnergy());
347  m_myRPCHitColl->Emplace(RPCid_phi, m_globalTime,
348  localPosition, trHelp.GenerateParticleLink(), localPostPosition,
349  aStep->GetTotalEnergyDeposit(),
350  aStep->GetStepLength(),
351  currentTrack->GetDefinition()->GetPDGEncoding(),
352  aStep->GetPreStepPoint()->GetKineticEnergy());
353 
354  return true;
355 }
Muon::nsw::STGTPSegments::moduleIDBits::stationPhi
constexpr uint8_t stationPhi
station Phi 1 to 8
Definition: NSWSTGTPDecodeBitmaps.h:129
RpcHitIdHelper::GetHelper
static const RpcHitIdHelper * GetHelper(unsigned int nGasGaps=2)
Definition: RpcHitIdHelper.cxx:23
dumpTgcDigiDeadChambers.gasGap
list gasGap
Definition: dumpTgcDigiDeadChambers.py:33
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
ZDC::sideC
BySideTypeMod sideC(-1)
dumpTgcDigiDeadChambers.stationName
dictionary stationName
Definition: dumpTgcDigiDeadChambers.py:30
TrackHelper.h
RPCSensitiveDetectorCosmics::m_currVertex
Amg::Vector3D m_currVertex
Definition: RPCSensitiveDetectorCosmics.h:118
createCablingJSON.doubletR
int doubletR
Definition: createCablingJSON.py:10
RPCSensitiveDetectorCosmics::m_isGeoModel
bool m_isGeoModel
Definition: RPCSensitiveDetectorCosmics.h:114
Trk::loc2
@ loc2
generic first and second local coordinate
Definition: ParamDefs.h:41
RPCSensitiveDetectorCosmics::m_vertex
Amg::Vector3D m_vertex
Definition: RPCSensitiveDetectorCosmics.h:117
RPCSensitiveDetectorCosmics::m_globH
Amg::Vector3D m_globH
Definition: RPCSensitiveDetectorCosmics.h:119
RPCSensitiveDetectorCosmics::m_muonHelper
const RpcHitIdHelper * m_muonHelper
Definition: RPCSensitiveDetectorCosmics.h:112
RpcHitIdHelper.h
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
RpcHitIdHelper::BuildRpcHitId
int BuildRpcHitId(const std::string &, const int, const int, const int, const int, const int, const int, const int) const
Definition: RpcHitIdHelper.cxx:102
python.changerun.kk
list kk
Definition: changerun.py:41
TrackHelper
Definition: TrackHelper.h:14
RPCSensitiveDetectorCosmics::m_momMag
double m_momMag
Definition: RPCSensitiveDetectorCosmics.h:116
lumiFormat.i
int i
Definition: lumiFormat.py:92
RPCSensitiveDetectorCosmics::m_myRPCHitColl
SG::WriteHandle< RPCSimHitCollection > m_myRPCHitColl
member data
Definition: RPCSensitiveDetectorCosmics.h:111
RPCSensitiveDetectorCosmics::RPCSensitiveDetectorCosmics
RPCSensitiveDetectorCosmics(const std::string &name, const std::string &hitCollectionName, unsigned int nGasGaps)
construction/destruction
Definition: RPCSensitiveDetectorCosmics.cxx:19
RPCSensitiveDetectorCosmics.h
trigbs_pickEvents.num
num
Definition: trigbs_pickEvents.py:76
CLHEPtoEigenConverter.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
RPCSensitiveDetectorCosmics::m_globalTime
double m_globalTime
Definition: RPCSensitiveDetectorCosmics.h:113
RPCSensitiveDetectorCosmics::ProcessHits
G4bool ProcessHits(G4Step *, G4TouchableHistory *) override final
Definition: RPCSensitiveDetectorCosmics.cxx:47
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
checkFileSG.fi
fi
Definition: checkFileSG.py:65
RPCSensitiveDetectorCosmics::Initialize
void Initialize(G4HCofThisEvent *) override final
member functions
Definition: RPCSensitiveDetectorCosmics.cxx:29
createCablingJSON.doubletPhi
int doubletPhi
Definition: createCablingJSON.py:11
TrackHelper::GenerateParticleLink
HepMcParticleLink GenerateParticleLink()
Generates a creates new HepMcParticleLink object on the stack based on GetUniqueID(),...
Definition: TrackHelper.h:35
Muon::nsw::STGTPSegments::moduleIDBits::stationEta
constexpr uint8_t stationEta
1 to 3
Definition: NSWSTGTPDecodeBitmaps.h:127
HitID
int HitID
Definition: GenericMuonSimHit.h:13
Trk::loc1
@ loc1
Definition: ParamDefs.h:40
RPCSensitiveDetectorCosmics::m_mom
Amg::Vector3D m_mom
Definition: RPCSensitiveDetectorCosmics.h:115