ATLAS Offline Software
RPCSensitiveDetector.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "RPCSensitiveDetector.h"
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 #include <sstream>
16 
19 #include "GaudiKernel/SystemOfUnits.h"
20 
21 // construction/destruction
22 RPCSensitiveDetector::RPCSensitiveDetector(const std::string& name, const std::string& hitCollectionName, unsigned int nGasGaps)
23  : G4VSensitiveDetector( name )
24  , m_myRPCHitColl( hitCollectionName )
25 {
27 }
28 
29 void RPCSensitiveDetector::Initialize(G4HCofThisEvent*)
30 {
31  if (!m_myRPCHitColl.isValid()) m_myRPCHitColl = std::make_unique<RPCSimHitCollection>();
32  //FIXME probably only need to call this bit at start of the event
33  //loop rather than the start of each G4Event.
34  if (verboseLevel>5) G4cout << "Initializing SD" << G4endl;
35 
36 }
37 
38 G4bool RPCSensitiveDetector::ProcessHits(G4Step* aStep,G4TouchableHistory*) {
39 
40  G4Track* track = aStep->GetTrack();
41 
43  if (track->GetDefinition()->GetPDGCharge() == 0.0) {
44  if (track->GetDefinition()!=G4Geantino::GeantinoDefinition()) {
45  return true;
46  }
47  }
48 
49  const G4TouchableHistory* touchHist = static_cast<const G4TouchableHistory*>(aStep->GetPreStepPoint()->GetTouchable());
50  G4ThreeVector position = aStep->GetPreStepPoint()->GetPosition();
51  G4ThreeVector postPosition = aStep->GetPostStepPoint()->GetPosition();
52  const G4AffineTransform trans = track->GetTouchable()->GetHistory()->GetTopTransform(); // from global to local
53 
54  // necessary to assign correct identifiers
55  int rpcIsRotated = 0;
56  // int layer = 0;
57 
58  std::string tech;
59  // fields for the RPC identifier construction
60  std::string stationName;
61  int stationEta= 0;
62  int stationPhi= 0;
63  int doubletR= 0;
64  // int doubletZ= 0;
65  int doubletPhi= 0;
66  int gasGap= 0;
67  // int eta_inversed=0;
68  // int phi_inversed=0;
69  int station_rotated=0; // tells us if the station was rotated before being positioned.
70  // if =1 we have to correct some IDs
71  int zNeg_original=0; // tells if the station at z<0 was obtained duplicating a station at z>0
72 
73  // RPC hit information
74  double globalTime = aStep->GetPreStepPoint()->GetGlobalTime();
75  Amg::Vector3D localPosition = Amg::Hep3VectorToEigen( trans.TransformPoint(position) );
76  Amg::Vector3D localPostPosition = Amg::Hep3VectorToEigen( trans.TransformPoint(postPosition) );
77  {
78  const Amg::Vector3D stepVector = localPostPosition - localPosition;
80  if (stepVector.mag()>std::numeric_limits<float>::epsilon() &&
81  std::abs(std::abs(Amg::angle(stepVector, Amg::Vector3D::UnitX()))
82  - 90.*Gaudi::Units::deg) < 0.0001* Gaudi::Units::deg) {
83  return true;
84  }
85  }
86  int mydbZ=0;
87  int mydbPMod=0;
88  int mydbP=0;
89  bool isAssembly = false;
90  // scan geometry tree to identify the hit channel
91  for (int i=touchHist->GetHistoryDepth();i>=0;i--) {
92 
93  std::string::size_type npos;
94  std::string volName = touchHist->GetVolume(i)->GetName();
95  std::string num=volName.substr(3,2);
96  if(num[0]==' ') num[0]=0;
97 
98  // check if this station is an assembly
99  if ((npos = volName.find("av_")) != std::string::npos &&
100  (npos = volName.find("impr_")) != std::string::npos) isAssembly = true;
101 
102  // stationName, stationEta, stationPhi
103  if ((npos = volName.find("station")) != std::string::npos && (!isAssembly)) {
104 
105  stationName = volName.substr(0,npos-1);
106 
107  int volCopyNo = touchHist->GetVolume(i)->GetCopyNo();
108 
109  if(abs(volCopyNo/1000)==1){
110  zNeg_original=1;
111  volCopyNo=volCopyNo%1000;
112  }
113 
114  stationEta = volCopyNo/100;
115  stationPhi = abs(volCopyNo%100);
116 
117  if(stationEta<0&&!zNeg_original) station_rotated=1;
118 
119  // stationName, stationEta, stationPhi
120  } else if ((npos = volName.find("RPC")) != std::string::npos && isAssembly) {
121  // vol name for Assembly components are
122  // av_WWW_impr_XXX_Muon::BMSxMDTxx_pv_ZZZ_NAME
123  // where WWW is ass. istance nr.
124  // XXX is comp. imprint nr.
125  // BMSxMDTxx is the name of the comp. log.Vol.
126  // x station sub-type; xx technology subtype
127  // ZZZ is the comp. number of order
128  // NAME is the comp. tag (geoIdentifierTag)
129  // for RPCs it is SwapdbPdbRdbZ[aaa]
130  // with aaa = doubletZ + doubletR*100 + dbphi*1000;
131  // aaa = -aaa if iswap == -1
132  // dbphi = 1 always but for S1 or S2 at doubletPhi = 2
133  // copy numbers for Ass.components are =
134  // CopyNoBase(= geoIdentifierTag of the assembly) + geoIdentifierTag of the component
135  // geoIdentifierTag of the component = Job
136  // geoIdentifierTag of the assembly = (sideC*10000 +
137  // mirsign*1000 + abs(zi)*100 + fi+1)*100000;
138  // mirsign = 1 if zi<0 and !mirrored; otherwise 0
139  std::string::size_type loc1,loc2;
140  if ((loc1 = volName.find("Muon::")) != std::string::npos) {
141  stationName = volName.substr(loc1+6,4); //type and subtype
142  }
143 
144  int volCopyNo = touchHist->GetVolume(i)->GetCopyNo();
145  int copyNrBase = int(volCopyNo/100000);
146  int sideC = int(copyNrBase/10000);
147  int zi = int((copyNrBase%1000)/100);
148  int mirfl = int((copyNrBase%10000)/1000);
149  int fi = int(copyNrBase%100);
150  if (sideC == 1) zi = -zi;
151  stationEta = zi;
152  stationPhi = fi;
153  zNeg_original = mirfl;
154 
155  if(stationEta<0&&!zNeg_original) station_rotated=1;
156 
157  // doubletZ = 1;
158  tech=volName.substr(npos,5);
159 
160  // now get the geoIdentifierTag of the rpc components
161  int gmID = 0;
162  if ((loc1 = volName.find('[')) != std::string::npos) {
163  if ((loc2 = volName.find(']', loc1+1)) != std::string::npos) {
164  //G4cout << "first [ is at "<<loc1<<" first ] at "<<loc2 << G4endl;
165  std::istringstream istrvar(volName.substr(loc1+1,loc2-loc1-1));
166  istrvar>>gmID;
167  }
168  }
169  int kk=gmID;
170 
171  if (kk < 0) rpcIsRotated=1;
172 
173  doubletR =(abs(kk)%1000)/100;
174  mydbZ = abs(int(kk%10));
175  mydbPMod = abs(int(kk/1000));
176  // doubleR, doubletZ
177  } else if ((npos = volName.find("rpccomponent")) != std::string::npos && (!isAssembly)) {
178 
179  std::string::size_type loc1,loc2;
180  tech=volName.substr(npos-5,5);
181  int gmID = 0;
182  if ((loc1 = volName.find('[')) != std::string::npos) {
183  if ((loc2 = volName.find(']', loc1+1)) != std::string::npos) {
184  std::istringstream istrvar(volName.substr(loc1+1,loc2-loc1-1));
185  istrvar>>gmID;
186  }
187  }
188  mydbZ = abs(int(gmID%10));
189  mydbPMod = abs(int(gmID/1000));
190 
191  int kk=touchHist->GetVolume(i)->GetCopyNo();
192 
193  if (kk < 0) rpcIsRotated=1;
194 
195  doubletR=(abs(kk)%1000)/100;
196 
197  } else if ((npos = volName.find("layer")) != std::string::npos) {
198 
199  int copyNo = touchHist->GetVolume(i)->GetCopyNo();
200 
201  if (copyNo == 1) {
202  rpcIsRotated ? gasGap = 2 : gasGap = 1;
203  } else if (copyNo ==2) {
204  rpcIsRotated ? gasGap = 1 : gasGap = 2;
205  } else if (copyNo ==3) {
206  gasGap = 3;
207  }
208  } else if((npos = volName.find("gas volume")) != std::string::npos) {
209 
210  int copyNo = touchHist->GetVolume(i)->GetCopyNo();
211  if (copyNo == 0) {
212  doubletPhi = 1;
213  } else if (copyNo == 10) {
214  doubletPhi = 2;
215  }
216  mydbP = doubletPhi;
217  int ngap_in_s=0;
218  int nstrippanel_in_s=0;
219  std::string::size_type loc1;
220  if ((loc1 = volName.find("gg_in_s")) != std::string::npos) {
221  std::istringstream istrvar(volName.substr(loc1-1,1));
222  istrvar>>ngap_in_s;
223  }
224  if ((loc1 = volName.find("sp_in_s")) != std::string::npos) {
225  std::istringstream istrvar(volName.substr(loc1-1,1));
226  istrvar>>nstrippanel_in_s;
227  }
228  if (ngap_in_s == 1 && nstrippanel_in_s == 2) {
229  if(localPosition.y()>0) mydbP=2;
230  else mydbP=1;
231  } else if (ngap_in_s == 1 && nstrippanel_in_s == 1) {
232  mydbP = mydbPMod;
233  }
234  }
235  }
236 
238  // correct wrong IDs due to station rotation. only doubletZ and doubletPhi are affected at this point
240 
241  if(station_rotated){
242  // doubletPhi correction
243  // note that this is correct also for ribs chambers
244  mydbP++;
245  if (mydbP>2) mydbP=1;
246  // G4cout << "Rcd PC - swap dbPhi because ch is MIRRORED "<<doubletPhi << G4endl;
247 
248  // strip numbering: if the station is rotated both eta and phi directions get inversed.
249  // commented out for geomodel!
250  }
251 
253 
254  // now we have the position in the gas gap, with correct axis orientation, and the offlineIDs *of the strip panel*
255  // nstrip is supposed to be calculated by RPC_Digitizer.
256 
257  // construct two (one in eta and one in phi) new RPC hits and store them in hit collection
258 
259  //construct the hit identifiers
260  if (verboseLevel>5) {
261  G4cout << "hit in station "<<stationName<< " on technology "<<tech << G4endl;
262  G4cout << "constructing ids (stName, stEta, stPhi, dr, dZ, dPhi)= "<<stationName<< " "<< stationEta<<" " << stationPhi<< " "<<doubletR<< " "<< mydbZ<< " "<<mydbP << G4endl;
263  }
264 
266  mydbZ, doubletR, gasGap, mydbP,0);
267 
269  mydbZ, doubletR, gasGap, mydbP,1);
270 
271  // retrieve track barcode
272  TrackHelper trHelp(aStep->GetTrack());
273 
274  //construct new rpc hit
275  m_myRPCHitColl->Emplace(RPCid_eta, globalTime,
276  localPosition, trHelp.GenerateParticleLink(), localPostPosition,
277  aStep->GetTotalEnergyDeposit(),
278  aStep->GetStepLength(),
279  track->GetDefinition()->GetPDGEncoding(),
280  aStep->GetPreStepPoint()->GetKineticEnergy());
281  m_myRPCHitColl->Emplace(RPCid_phi, globalTime,
282  localPosition, trHelp.GenerateParticleLink(), localPostPosition,
283  aStep->GetTotalEnergyDeposit(),
284  aStep->GetStepLength(),
285  track->GetDefinition()->GetPDGEncoding(),
286  aStep->GetPreStepPoint()->GetKineticEnergy());
287 
288  return true;
289 }
290 
Muon::nsw::STGTPSegments::moduleIDBits::stationPhi
constexpr uint8_t stationPhi
station Phi 1 to 8
Definition: NSWSTGTPDecodeBitmaps.h:161
RpcHitIdHelper::GetHelper
static const RpcHitIdHelper * GetHelper(unsigned int nGasGaps=2)
Definition: RpcHitIdHelper.cxx:23
dumpTgcDigiDeadChambers.gasGap
list gasGap
Definition: dumpTgcDigiDeadChambers.py:33
RPCSensitiveDetector::m_muonHelper
const RpcHitIdHelper * m_muonHelper
Definition: RPCSensitiveDetector.h:112
Amg::angle
double angle(const Amg::Vector3D &v1, const Amg::Vector3D &v2)
calculates the opening angle between two vectors
Definition: GeoPrimitivesHelpers.h:41
dumpTgcDigiDeadChambers.stationName
dictionary stationName
Definition: dumpTgcDigiDeadChambers.py:30
RPCSensitiveDetector::m_myRPCHitColl
SG::WriteHandle< RPCSimHitCollection > m_myRPCHitColl
member data
Definition: RPCSensitiveDetector.h:111
TrackHelper.h
RPCSensitiveDetector::ProcessHits
G4bool ProcessHits(G4Step *, G4TouchableHistory *) override final
Definition: RPCSensitiveDetector.cxx:38
createCablingJSON.doubletR
int doubletR
Definition: createCablingJSON.py:15
deg
#define deg
Definition: SbPolyhedron.cxx:17
Trk::loc2
@ loc2
generic first and second local coordinate
Definition: ParamDefs.h:35
RPCSensitiveDetector.h
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:39
TrackHelper
Definition: TrackHelper.h:14
lumiFormat.i
int i
Definition: lumiFormat.py:85
RPCSensitiveDetector::RPCSensitiveDetector
RPCSensitiveDetector(const std::string &name, const std::string &hitCollectionName, unsigned int nGasGaps)
construction/destruction
Definition: RPCSensitiveDetector.cxx:22
trigbs_pickEvents.num
num
Definition: trigbs_pickEvents.py:76
CLHEPtoEigenConverter.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
RPCSensitiveDetector::Initialize
void Initialize(G4HCofThisEvent *) override final
member functions
Definition: RPCSensitiveDetector.cxx:29
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
GeoPrimitivesHelpers.h
RPDUtils::sideC
unsigned constexpr int sideC
Definition: RPDUtils.h:15
createCablingJSON.doubletPhi
int doubletPhi
Definition: createCablingJSON.py:16
xAOD::track
@ track
Definition: TrackingPrimitives.h:513
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:159
HitID
int HitID
Definition: GenericMuonSimHit.h:13
Trk::loc1
@ loc1
Definition: ParamDefs.h:34