ATLAS Offline Software
RadLengthAction.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 "RadLengthAction.h"
7 #include "MCTruth/TrackHelper.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 
34 namespace G4UA
35 {
36 
38  : m_config(config)
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
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=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 = 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
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
G4UA::RadLengthAction::EndOfEventAction
virtual void EndOfEventAction(const G4Event *) override
Definition: RadLengthAction.cxx:194
G4UA::RadLengthAction::m_SDCSC
G4VSensitiveDetector * m_SDCSC
Definition: RadLengthAction.h:74
SGTest::store
TestStore store
Definition: TestStore.cxx:23
G4UA::RadLengthAction::EndOfRunAction
virtual void EndOfRunAction(const G4Run *) override
Definition: RadLengthAction.cxx:163
G4UA::RadLengthAction::topvolmap
std::map< std::string, G4VPhysicalVolume * > topvolmap
Definition: RadLengthAction.h:59
G4UA::RadLengthAction::treeMap
std::map< std::string, TTree * > treeMap
Definition: RadLengthAction.h:63
G4UA
for nSW
Definition: CalibrationDefaultProcessing.h:19
TrackHelper.h
ServiceAccessor.h
G4UA::RadLengthAction::UserSteppingAction
virtual void UserSteppingAction(const G4Step *) override
Definition: RadLengthAction.cxx:218
xyz
#define xyz
G4UA::RadLengthAction::BeginOfEventAction
virtual void BeginOfEventAction(const G4Event *) override
Definition: RadLengthAction.cxx:169
G4UA::RadLengthAction::variables
std::map< std::string, std::vector< double > > variables
Definition: RadLengthAction.h:68
RadLengthAction.h
G4UA::RadLengthAction::chargePrimary
double chargePrimary
Definition: RadLengthAction.h:55
G4UA::RadLengthAction::MuChamberPassed
bool MuChamberPassed
Definition: RadLengthAction.h:51
G4UA::RadLengthAction::phiPrimary
double phiPrimary
Definition: RadLengthAction.h:55
G4UA::RadLengthAction::BeginOfRunAction
virtual void BeginOfRunAction(const G4Run *) override
Definition: RadLengthAction.cxx:50
config
Definition: PhysicsAnalysis/AnalysisCommon/AssociationUtils/python/config.py:1
cm
const double cm
Definition: Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/FCAL_ChannelMap.cxx:25
TrackHelper
Definition: TrackHelper.h:14
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
ParticleGun_EoverP_Config.mom
mom
Definition: ParticleGun_EoverP_Config.py:63
G4UA::RadLengthAction::MuTriggerPassed
bool MuTriggerPassed
Definition: RadLengthAction.h:52
lumiFormat.i
int i
Definition: lumiFormat.py:85
G4UA::RadLengthAction::etaPrimary
double etaPrimary
Definition: RadLengthAction.h:55
G4UA::RadLengthAction::RadLengthAction
RadLengthAction(const Config &config)
Definition: RadLengthAction.cxx:37
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
G4UA::RadLengthAction::m_hSvc
ServiceHandle< ITHistSvc > m_hSvc
Definition: RadLengthAction.h:78
G4UA::RadLengthAction::fillVariables
void fillVariables(const std::vector< double > &varvec, const std::string &name)
Definition: RadLengthAction.cxx:284
TrackHelper::IsSecondary
bool IsSecondary() const
Definition: TrackHelper.cxx:30
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
G4UA::RadLengthAction::Config
Definition: RadLengthAction.h:32
G4UA::RadLengthAction::m_SDMDT
G4VSensitiveDetector * m_SDMDT
Definition: RadLengthAction.h:72
G4UA::RadLengthAction::m_SDTGC
G4VSensitiveDetector * m_SDTGC
Definition: RadLengthAction.h:73
TrackHelper::IsPrimary
bool IsPrimary() const
Definition: TrackHelper.cxx:15
G4UA::RadLengthAction::m_SDRPC
G4VSensitiveDetector * m_SDRPC
Definition: RadLengthAction.h:75
CaloCellTimeCorrFiller.filename
filename
Definition: CaloCellTimeCorrFiller.py:24
test_pyathena.counter
counter
Definition: test_pyathena.py:15
G4UA::RadLengthAction::Config::VolumeDepthLevel
int VolumeDepthLevel
Definition: RadLengthAction.h:35
G4UA::RadLengthAction::m_config
Config m_config
Definition: RadLengthAction.h:47
fitman.k
k
Definition: fitman.py:528