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