ATLAS Offline Software
Loading...
Searching...
No Matches
RPCSensitiveDetectorCosmics Class Reference

#include <RPCSensitiveDetectorCosmics.h>

Inheritance diagram for RPCSensitiveDetectorCosmics:
Collaboration diagram for RPCSensitiveDetectorCosmics:

Public Member Functions

 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

Private Member Functions

 FRIEND_TEST (RPCSensitiveDetectorCosmicstest, Initialize)
 FRIEND_TEST (RPCSensitiveDetectorCosmicstest, ProcessHits)

Private Attributes

std::string m_hitCollectionName
 member data
RPCSimHitCollectionm_myRPCHitColl {nullptr}
AtlasG4EventUserInfom_g4UserEventInfo {nullptr}
const RpcHitIdHelperm_muonHelper
double m_globalTime
bool m_isGeoModel
Amg::Vector3D m_mom
double m_momMag
Amg::Vector3D m_vertex
Amg::Vector3D m_currVertex
Amg::Vector3D m_globH

Detailed Description

Author
Andre.nosp@m.a.Di.nosp@m.Simon.nosp@m.e@ce.nosp@m.rn.ch

Class methods and properties

The method RPCSensitiveDetectorCosmics::ProcessHits is executed by the G4 kernel each time a particle crosses one of the RPC gas gaps. Navigating with the touchableHistory method GetHistoryDepth() through the hierarchy of volumes crossed by the particle, the Sensitive Detector determines the correct set of Simulation Identifiers to associate to each hit. The RPC SimIDs are 32-bit unsigned integers, built using the MuonSimEvent/RpcHitIdHelper class which inherits from the MuonHitIdHelper base class.

We describe here how each field of the identifier is determined.

1) stationName, stationEta, stationPhi: when a volume is found in the hierarchy whose name contains the substring "station", the stationName is extracted from the volume's name. stationEta and stationPhi values are calculated starting from the volume's copy number.

2) doubletR: when a volume is found in the hierarchy whose name contains the substring "rpccomponent", its copy number is used to calulate the doubletR of the hit.

3) gasGap: the substring "layer" is searched through the names of the volumes in the hierarchy. When a the volume is found, its copy number is used, together with the sign of the copy number of the "rpccomponent" to decide what is the correct gasGap value.

4) doubletPhi: when the volume with the substring "gas volume" in its name is found, its copy number is enough to determine the doubletPhi of the hit if the hit is registered in a standard chamber. For special chambers (i.e. chambers with only one gas gap per layer readout by two strip panels per direction, or chambers in the ribs) some a special attribution is done using also the stationName.

5) doubletZ: "gazGap" is the required substring in the volume's name. doubletZ attribution is fairly complicated. For standard chambers it just uses the sign of the copy number of the "rpccomponent", but severa arrangements (based on the stationName and the technology name) are needed for special chambers.

6) the doubletPhi calculated as described above needs one further correction for some chambers to take into account chamber rotation before placement in the spectrometer. This is done just before creating the hit.

notes:

1) presently, chamber efficiency is assumed to be 100% at the level of the Sensitive Detector, i.e. two hits (one in eta and one in phi) are created each time the sensitive detector is created.

2) the hits created as described above contain information about their local position in the gas gap and the simulation identifier of the strip panel

3) the strip number is not assigned by the sensitive detector, and must be calculated by the digitization algorithm.

4) points 2 and 3 are due to the necessity of not introducing any dependency on the geometry description in the Sensitive Detector.

5) the present version of the Sensitive Detector produces hits which are different depending on whether hand coded G4 geometry or GeoModel is used for the geometrical description of the setup. When hand coded geometry is used, both GeoModel and the old MuonDetDescr can be used for digitization (using a proper tag of RPC_Digitization), while if GeoModel is used in the simulation, it must be used also in the digitization.

6) for each hit, the time of flight (the G4 globalTime), is recorded and associated to the hit.

7) the RPCHit object contains: the SimID, the globalTime, the hit local position and the track barcode.

Definition at line 98 of file RPCSensitiveDetectorCosmics.h.

Constructor & Destructor Documentation

◆ RPCSensitiveDetectorCosmics()

RPCSensitiveDetectorCosmics::RPCSensitiveDetectorCosmics ( const std::string & name,
const std::string & hitCollectionName,
unsigned int nGasGaps )

construction/destruction

Definition at line 22 of file RPCSensitiveDetectorCosmics.cxx.

23 : G4VSensitiveDetector( name )
24 , m_hitCollectionName( hitCollectionName )
25 , m_globalTime(0.)
26 , m_isGeoModel(true)
27 , m_momMag(0.)
28{
30}
static const RpcHitIdHelper * GetHelper(unsigned int nGasGaps=2)

Member Function Documentation

◆ FRIEND_TEST() [1/2]

RPCSensitiveDetectorCosmics::FRIEND_TEST ( RPCSensitiveDetectorCosmicstest ,
Initialize  )
private

◆ FRIEND_TEST() [2/2]

RPCSensitiveDetectorCosmics::FRIEND_TEST ( RPCSensitiveDetectorCosmicstest ,
ProcessHits  )
private

◆ Initialize()

void RPCSensitiveDetectorCosmics::Initialize ( G4HCofThisEvent * )
finaloverride

member functions

Definition at line 32 of file RPCSensitiveDetectorCosmics.cxx.

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}
AtlasHitsVector< RPCSimHit > RPCSimHitCollection
static AtlasG4EventUserInfo * GetEventUserInfo()
Eigen::Matrix< double, 3, 1 > Vector3D

◆ ProcessHits()

G4bool RPCSensitiveDetectorCosmics::ProcessHits ( G4Step * aStep,
G4TouchableHistory *  )
finaloverride

Definition at line 54 of file RPCSensitiveDetectorCosmics.cxx.

54 {
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
Amg::Vector3D Hep3VectorToEigen(const CLHEP::Hep3Vector &CLHEPvector)
Converts a CLHEP-based CLHEP::Hep3Vector into an Eigen-based Amg::Vector3D.
constexpr uint8_t stationPhi
station Phi 1 to 8
unsigned int constexpr sideC
Definition RPDUtils.h:15
@ loc2
generic first and second local coordinate
Definition ParamDefs.h:35
@ loc1
Definition ParamDefs.h:34

Member Data Documentation

◆ m_currVertex

Amg::Vector3D RPCSensitiveDetectorCosmics::m_currVertex
private

Definition at line 121 of file RPCSensitiveDetectorCosmics.h.

◆ m_g4UserEventInfo

AtlasG4EventUserInfo* RPCSensitiveDetectorCosmics::m_g4UserEventInfo {nullptr}
private

Definition at line 114 of file RPCSensitiveDetectorCosmics.h.

114{nullptr};

◆ m_globalTime

double RPCSensitiveDetectorCosmics::m_globalTime
private

Definition at line 116 of file RPCSensitiveDetectorCosmics.h.

◆ m_globH

Amg::Vector3D RPCSensitiveDetectorCosmics::m_globH
private

Definition at line 122 of file RPCSensitiveDetectorCosmics.h.

◆ m_hitCollectionName

std::string RPCSensitiveDetectorCosmics::m_hitCollectionName
private

member data

Definition at line 112 of file RPCSensitiveDetectorCosmics.h.

◆ m_isGeoModel

bool RPCSensitiveDetectorCosmics::m_isGeoModel
private

Definition at line 117 of file RPCSensitiveDetectorCosmics.h.

◆ m_mom

Amg::Vector3D RPCSensitiveDetectorCosmics::m_mom
private

Definition at line 118 of file RPCSensitiveDetectorCosmics.h.

◆ m_momMag

double RPCSensitiveDetectorCosmics::m_momMag
private

Definition at line 119 of file RPCSensitiveDetectorCosmics.h.

◆ m_muonHelper

const RpcHitIdHelper* RPCSensitiveDetectorCosmics::m_muonHelper
private

Definition at line 115 of file RPCSensitiveDetectorCosmics.h.

◆ m_myRPCHitColl

RPCSimHitCollection* RPCSensitiveDetectorCosmics::m_myRPCHitColl {nullptr}
private

Definition at line 113 of file RPCSensitiveDetectorCosmics.h.

113{nullptr};

◆ m_vertex

Amg::Vector3D RPCSensitiveDetectorCosmics::m_vertex
private

Definition at line 120 of file RPCSensitiveDetectorCosmics.h.


The documentation for this class was generated from the following files: