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