ATLAS Offline Software
Loading...
Searching...
No Matches
RadLengthAction.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "RadLengthAction.h"
8
9#include <iostream>
10#include <string>
11#include <map>
12#include <vector>
13#include <math.h>
14#include <TTree.h>
15
16#include "GaudiKernel/ISvcLocator.h"
17#include "GaudiKernel/MsgStream.h"
18
19#include "G4PrimaryParticle.hh"
20#include "G4PrimaryVertex.hh"
21#include "G4Event.hh"
22#include "G4TouchableHistory.hh"
23#include "G4Step.hh"
24#include "G4StepPoint.hh"
25#include "G4Track.hh"
26
27#include "G4SDManager.hh"
28#include "G4VSensitiveDetector.hh"
29#include "G4LogicalVolumeStore.hh"
30#include "G4LogicalVolume.hh"
31#include "G4VPhysicalVolume.hh"
32#include "G4Material.hh"
33
34namespace G4UA
35{
36
39 , m_SDMDT(nullptr)
40 , m_SDTGC(nullptr)
41 , m_SDCSC(nullptr)
42 , m_SDRPC(nullptr)
43 , m_hSvc("THistSvc", "RadLengthAction")
44 {
45 }
46
47
48 // BeginOfRunAction used for initialization of the most crucial maps,
49 // registering trees and reading depth level from jobOptions
51 {
52 // getting level of depth from jobOptions
53 // depth = atof( theProperties["VolumeDepthLevel"].c_str() );
54
55 // creating reference to sensitive detectors of muonsystem
56 // later on used for comparison in Stepping
57 G4SDManager *SDM=G4SDManager::GetSDMpointer();
58 m_SDMDT = (G4VSensitiveDetector*) SDM->FindSensitiveDetector("AMS");
59 m_SDTGC = (G4VSensitiveDetector*) SDM->FindSensitiveDetector("TMS");
60 m_SDCSC = (G4VSensitiveDetector*) SDM->FindSensitiveDetector("CMS");
61 m_SDRPC = (G4VSensitiveDetector*) SDM->FindSensitiveDetector("RMS");
62
63
64 // clearing the maps with comparison volumes, trees and variables
65 topvolmap.clear();
66 treeMap.clear();
67 variables.clear();
68
69 // creating volume store
70 G4LogicalVolumeStore *store = G4LogicalVolumeStore::GetInstance();
71 // getting most top volume "Atlas::Atlas" by hand
72 G4LogicalVolume* atlas = store->GetVolume("Atlas::Atlas");
73
74 // logical volume vector, initialized with atlas only
75 // later on filled with all logicals of depth level
76 std::vector<G4LogicalVolume*> logvec;
77 logvec.push_back(atlas);
78
79 // physical volume vector later on used for topvolmap and names
80 std::vector<G4VPhysicalVolume*> physvec;
81
82 // counter for loop up to depth level
83 int counter = 0;
84
85 // loop to fill physvec with all physical volumes of depth level
86 while(counter != m_config.VolumeDepthLevel){
87 // counter increase up to depth
88 counter++;
89
90 // create tmplogvec to be filled with (logical) daughters of counter depth level
91 std::vector<G4LogicalVolume*> tmplogvec;
92
93 // looping on logical vector of previous depth level
94 for(G4LogicalVolume* logvol : logvec) {
95 for(unsigned int k=0; k<logvol->GetNoDaughters();k++){
96 // dumping all logical daughters for next level
97 tmplogvec.push_back(logvol->GetDaughter(k)->GetLogicalVolume());
98 // dumping the corresponding physical if not made of gas or last depth level where all are dumped
99 if((logvol->GetDaughter(k)->GetLogicalVolume()->GetMaterial()->GetRadlen()<100*CLHEP::cm) || (counter == m_config.VolumeDepthLevel)){
100 physvec.push_back(logvol->GetDaughter(k));
101 }
102 }
103 }
104
105 // logical vector is put to the tmplogvec (with daughters) for next stage
106 // to physvec all not gas daughters of this level where already added
107 logvec=std::move(tmplogvec);
108
109 }
110
111 // loop on physvec to put the volumes in the topvolmap using their name
112 // for comparison in Stepping and initializing all other maps
113 for (G4VPhysicalVolume* physvol : physvec) {
114 std::string fulldaughtername = physvol->GetName();
115 std::string daughtername;
116 std::string::size_type npos;
117 npos=fulldaughtername.find("::");
118 // nicer naming for depth level =1
119 if(npos!=std::string::npos && m_config.VolumeDepthLevel==1) daughtername = fulldaughtername.substr(0,npos);
120 else daughtername = std::move(fulldaughtername);
121 topvolmap[daughtername]=physvol;
122 }
123
124 // adding by hand two additional names to topvolmap (without volume)
125 // due to initialization purpose of topvolmap
126 topvolmap["ToMuChamber"] = 0;
127 topvolmap["ToMuTrigger"] = 0;
128
129 // using topvolmap to initialize treemap (trees with volumenames)
130 // and variables map of vectors with FIXED SIZE TO NUMBER OF VARIABLES TO BE DUMPED
131 for (auto& p : topvolmap) {
132 treeMap[p.first]=new TTree(TString(p.first), TString(p.first));
133 variables[p.first].resize(12);
134 }
135
136 // get the THistoSvc
137 if(m_hSvc.retrieve().isFailure()) return;
138
139 // using already initialized treeMap to register the trees with volname
140 // and branches which are REFERENCED to the components of the corresponding
141 // entry in variables map
142 for (auto& p : treeMap) {
143 std::string filename= "/RadLengthAction/";
144 std::string treepath= filename+p.first;
145 m_hSvc->regTree(treepath.c_str(), treeMap[p.first]).ignore();
146 //if (!hSvc) log()<< MSG::ERROR << "Cannot register Tree!" << p.first << endreq;
147 treeMap[p.first]->Branch("EnergyLoss", &variables[p.first].at(0), "EnergyLoss/D");
148 treeMap[p.first]->Branch("RadLength", &variables[p.first].at(1), "RadLength/D");
149 treeMap[p.first]->Branch("Intlength", &variables[p.first].at(2), "Intlength/D");
150 treeMap[p.first]->Branch("InitialEta", &variables[p.first].at(3), "InitialEta/D");
151 treeMap[p.first]->Branch("InitialPhi", &variables[p.first].at(4), "InitialPhi/D");
152 treeMap[p.first]->Branch("PointEta", &variables[p.first].at(5), "PointEta/D");
153 treeMap[p.first]->Branch("PointPhi", &variables[p.first].at(6), "PointPhi/D");
154 treeMap[p.first]->Branch("PointX", &variables[p.first].at(7), "PointX/D");
155 treeMap[p.first]->Branch("PointY", &variables[p.first].at(8), "PointY/D");
156 treeMap[p.first]->Branch("PointZ", &variables[p.first].at(9), "PointZ/D");
157 treeMap[p.first]->Branch("PointR", &variables[p.first].at(10), "PointR/D");
158 treeMap[p.first]->Branch("Charge", &variables[p.first].at(11), "Charge/D");
159 }
160 }
161
162 // empty EndOfRunAction
164 {
165
166 }
167
168 // BeginOfEventAction used to get variables of primary particle and reinitialization
169 void RadLengthAction::BeginOfEventAction(const G4Event* anEvent)
170 {
171
172 // getting variables of the primary particle
173 G4PrimaryVertex *vert=anEvent->GetPrimaryVertex(0);
174 // vert->SetPosition(0.0,0.0,0.0);
175 G4PrimaryParticle *part=vert->GetPrimary();
176 G4ThreeVector mom=part->GetMomentum();
177 etaPrimary=mom.eta();
178 phiPrimary=mom.phi();
179 chargePrimary=part->GetCharge();
180 G4cout<<"Begin Of Event"<<" "<<(double)vert->GetX0()<<" "<<(double)vert->GetY0()<<" "<<(double)vert->GetZ0()<< G4endl;
181 G4cout<<"Begin Of Event"<<" "<<(double)mom[0]<<" "<<(double)mom[1]<<" "<<(double)mom[2]<< G4endl;
182
183 // putting passflags for muon chambers/trigger (back) to false
184 MuChamberPassed = false;
185 MuTriggerPassed = false;
186
187 // reinitialize the variables vector for this event
188 for (auto& p : variables) {
189 for(unsigned int i=0; i< variables[p.first].size(); i++) variables[p.first].at(i)=0;
190 }
191 }
192
193 // EndOfEvent used for filling all trees (branches are already refering to variables)
195 {
196
197 //for the case there was never a chamber passed set eloss to 1 radlength/intlength to -1
198 if(!MuChamberPassed){
199 variables["ToMuChamber"].at(0) = 1.;
200 variables["ToMuChamber"].at(1) = -1.;
201 variables["ToMuChamber"].at(2) = -1.;
202 }
203
204 //for the case there was never a trigger passed set eloss to 1 radlength/intlength to -1
205 if(!MuChamberPassed){
206 variables["ToMuTrigger"].at(0) = 1.;
207 variables["ToMuTrigger"].at(1) = -1.;
208 variables["ToMuTrigger"].at(2) = -1.;
209 }
210
211
212 for (auto& p : treeMap) {
213 treeMap[p.first]->Fill();
214 }
215 }
216
217 // Stepping to get the variables and make volume association
218 void RadLengthAction::UserSteppingAction(const G4Step* aStep)
219 {
220
221 // killing secondaries to save computing time, perhaps
222 if(TrackHelper(aStep->GetTrack()).IsSecondary()) aStep->GetTrack()->SetTrackStatus(fStopAndKill);
223
224 // entering primary particle
225 if(TrackHelper(aStep->GetTrack()).IsPrimary()) {
226
227 // get touchable history since used often
228 const G4TouchableHistory* touchHist =
229 static_cast<const G4TouchableHistory*>(aStep->GetPreStepPoint()->GetTouchable());
230
231 // get point before Stepping was started
232 G4ThreeVector xyz = (G4ThreeVector) aStep->GetPreStepPoint()->GetPosition();
233
234 // get radlength and intlength of volumes passed with this Stepping
235 // double radl=touchHist->GetVolume()->GetLogicalVolume()->GetMaterial()->GetRadlen();
236 // double intl=touchHist->GetVolume()->GetLogicalVolume()->GetMaterial()->GetNuclearInterLength();
237 double radl=aStep->GetPreStepPoint()->GetMaterial()->GetRadlen();
238 double intl=aStep->GetPreStepPoint()->GetMaterial()->GetNuclearInterLength();
239
240 // get the steplength for calculation X0 and intlength
241 double stepl=aStep->GetStepLength();
242 G4cout<<aStep->GetPreStepPoint()->GetMaterial()->GetName()<<" "<<radl<<" "<<stepl<<" "<<stepl/radl<<" "<<(double) xyz[0]<<" "<<(double) xyz[1]<<" "<< (double) xyz[2]<<G4endl;
243 // define and fill vector for the FIXED NUMBER of variables which should be dumped later on
244 const unsigned int nVariablesToSave(12);
245 std::vector<double> varvec(nVariablesToSave);
246 varvec.at(0) = (double) aStep->GetDeltaEnergy();
247 varvec.at(1) = (double) stepl/radl;
248 varvec.at(2) = (double) stepl/intl;
249 varvec.at(3) = (double) etaPrimary;
250 varvec.at(4) = (double) phiPrimary;
251 varvec.at(5) = (double) xyz.pseudoRapidity();
252 varvec.at(6) = (double) xyz.phi();
253 varvec.at(7) = (double) xyz[0];
254 varvec.at(8) = (double) xyz[1];
255 varvec.at(9) = (double) xyz[2];
256 varvec.at(10) = (double) sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]);
257 varvec.at(11) = (double) chargePrimary;
258
259 // loop on topvolmap to search for mother of current volume on volume depth level
260 // dump the variables in corresponding component of variables map
261 for (auto& p : topvolmap) {
262 if(p.second == touchHist->GetVolume(touchHist->GetHistoryDepth()-m_config.VolumeDepthLevel) ){
263 this->fillVariables(varvec, p.first);
264 }
265 }
266
267 // get sensitive detector of current volume
268 G4VSensitiveDetector* SD = (G4VSensitiveDetector*) touchHist->GetVolume()->GetLogicalVolume()->GetSensitiveDetector();
269
270 // set muon chamber pass flag true up to end of event and dump
271 // variables collected up to this point in variables map
272 if(SD==m_SDCSC || SD==m_SDMDT) MuChamberPassed = true;
273 if(!MuChamberPassed) this->fillVariables(varvec, "ToMuChamber");
274
275 // set muon trigger pass flag true up to end of event and dump
276 // variables collected up to this point in variables map
277 if(SD==m_SDRPC || SD==m_SDTGC) MuTriggerPassed = true;
278 if(!MuTriggerPassed) this->fillVariables(varvec, "ToMuTrigger");
279
280 }//end primary particle
281 }
282
283 // how variables should be dumped in variables map
284 void RadLengthAction::fillVariables(const std::vector<double>& varvec, const std::string& name){
285 // first three components should be added (deltaenergy, radlength, intlength)
286 for(unsigned int i = 0; i<3; i++) variables[name].at(i) += varvec.at(i);
287 // other components should be overwritten
288 // (last value inside the volume will be kept by change and dumped in EndOfEvent)
289 for(unsigned int j = 3; j<12; j++) variables[name].at(j) = varvec.at(j);
290 }
291} //namespace G4UA
#define xyz
virtual void BeginOfEventAction(const G4Event *) override
std::map< std::string, TTree * > treeMap
virtual void EndOfRunAction(const G4Run *) override
G4VSensitiveDetector * m_SDMDT
std::map< std::string, std::vector< double > > variables
G4VSensitiveDetector * m_SDTGC
G4VSensitiveDetector * m_SDRPC
G4VSensitiveDetector * m_SDCSC
void fillVariables(const std::vector< double > &varvec, const std::string &name)
RadLengthAction(const Config &config)
virtual void EndOfEventAction(const G4Event *) override
virtual void UserSteppingAction(const G4Step *) override
ServiceHandle< ITHistSvc > m_hSvc
std::map< std::string, G4VPhysicalVolume * > topvolmap
virtual void BeginOfRunAction(const G4Run *) override
bool IsPrimary() const
bool IsSecondary() const