ATTPCROOT  0.3.0-alpha
A ROOT-based framework for analyzing data from active target detectors
AtSimpleSimulation.cxx
Go to the documentation of this file.
1 
2 #include "AtSimpleSimulation.h"
3 
4 #include "AtELossModel.h"
5 #include "AtMCPoint.h"
6 #include "AtSpaceChargeModel.h" // for AtSpaceChargeModel
7 
8 #include <FairLogger.h>
9 #include <FairRootManager.h>
10 
11 #include <TClonesArray.h> // for TClonesArray
12 #include <TGeoManager.h>
13 #include <TGeoNode.h>
14 #include <TGeoVolume.h>
15 #include <TObject.h> // for TObject
16 
17 #include <cmath> // for sqrt
18 #include <stdexcept> // for invalid_argument
19 #include <utility> // for pair
20 
21 thread_local TClonesArray AtSimpleSimulation::fMCPoints("AtMCPoint");
22 thread_local int AtSimpleSimulation::fTrackID = 0;
23 
25 {
26  TGeoManager *geo = TGeoManager::Import(geoFile.c_str());
27 
28  if (gGeoManager == nullptr)
29  LOG(fatal) << "Failed to load geometry file " << geoFile << " " << geo;
30 }
32 {
33  if (gGeoManager == nullptr)
34  LOG(fatal) << "No geometry file loaded!";
35 }
36 
38 {
39  if (A < other.A) {
40  return true;
41  } else if (A > other.A) {
42  return false;
43  } else {
44  return Z < other.Z;
45  }
46 }
47 
49 TGeoVolume *AtSimpleSimulation::GetVolume(const XYZPoint &point)
50 {
51  auto pointCm = point / 10.;
52  {
53  std::lock_guard<std::mutex> lock(fGeoMutex);
54  TGeoNode *node = gGeoManager->FindNode(pointCm.X(), pointCm.Y(), pointCm.Z());
55  if (node == nullptr) {
56  return nullptr;
57  }
58  return node->GetVolume();
59  }
60 }
61 
62 bool AtSimpleSimulation::IsInVolume(const std::string &volName, const XYZPoint &point)
63 {
64 
65  TGeoVolume *volume = GetVolume(point);
66  if (volume == nullptr || volName != std::string(volume->GetName())) {
67  return false;
68  }
69 
70  return true;
71 }
72 
74 {
75  TGeoVolume *volume = GetVolume(point);
76  if (volume == nullptr) {
77  return "";
78  }
79  return volume->GetName();
80 }
81 
82 void AtSimpleSimulation::AddModel(int Z, int A, ModelPtr model)
83 {
84  ParticleID id = {
85  .A = A,
86  .Z = Z,
87  };
88 
89  fModels[id] = model;
90 }
91 
92 void AtSimpleSimulation::SimulateParticle(int Z, int A, const XYZPoint &iniPos, const PxPyPzEVector &iniMom)
93 {
94  auto modelIt = fModels.find({A, Z});
95  if (modelIt == fModels.end())
96  throw std::invalid_argument("Missing energy loss model for Z:" + std::to_string(Z) + " A:" + std::to_string(A));
97  if (!IsInVolume("drift_volume", iniPos))
98  throw std::invalid_argument("Position of particle is not in active volume but is in " + GetVolumeName(iniPos));
99 
100  SimulateParticle(modelIt->second, iniPos, iniMom);
101 }
102 
103 void AtSimpleSimulation::SimulateParticle(ModelPtr model, const XYZPoint &iniPos, const PxPyPzEVector &iniMom)
104 {
105  // This is a new track
106  fTrackID++;
107 
108  auto pos = iniPos;
109  auto mom = iniMom;
110  double length = 0;
111 
112  // Go until we exit the volume or the KE is less than 1keV
113  while (IsInVolume("drift_volume", pos) && mom.E() - mom.M() > 1e-3) {
114 
115  if (isnan(pos.X()) || isnan(mom.X())) {
116  LOG(error) << "Failed to simulate a point with nan!";
117  return;
118  }
119  // Direction particle is traveling
120  auto dir = mom.Vect().Unit();
121 
122  // Get the energy loss from the model
123  double KE = mom.E() - mom.M();
124  double eLoss = model->GetEnergyLoss(KE, fDistStep);
125 
126  // Update the momentum from the energy loss model. Assume the energy loss does not change
127  // the direction of the particle.
128  // newMom (x/y/z) =
129  auto E = mom.E() - eLoss;
130  double p = sqrt(E * E - mom.M2());
131  mom.SetPxPyPzE(dir.X() * p, dir.Y() * p, dir.Z() * p, E);
132 
133  LOG(debug) << mom << " " << mom.M() << " " << iniMom.M();
134 
135  pos += dir * fDistStep;
136  length += fDistStep;
137  AddHit(eLoss, pos, mom, length);
138  }
139 }
140 
142 {
143  fMCPoints.Clear();
144  fTrackID = 0;
145 }
146 
150 void AtSimpleSimulation::AddHit(double ELoss, const XYZPoint &pos, const PxPyPzEVector &mom, double length)
151 {
152  LOG(debug) << "Adding a hit at element " << fMCPoints.GetEntriesFast() << " in TClonesArray.";
153 
154  auto *mcPoint = dynamic_cast<AtMCPoint *>(fMCPoints.ConstructedAt(fMCPoints.GetEntriesFast(), "C"));
155 
156  mcPoint->SetTrackID(fTrackID);
157  mcPoint->SetLength(length / 10.); // Convert to cm
158  mcPoint->SetEnergyLoss(ELoss / 1000.); // Convert to GeV
159  mcPoint->SetVolName("drift_volume");
160 
161  if (fSCModel) {
162  // In the simulation z = 0 is the window and z=1000 is the pad plane.
163  // In the data analysis that is flipped, so we must adjust the z value, apply SC and move back
164  auto posExpCoord = pos;
165  posExpCoord.SetZ(1000 - pos.Z());
166  auto corrExpCoord = fSCModel->ApplySpaceCharge(posExpCoord);
167  corrExpCoord.SetZ(1000 + corrExpCoord.Z());
168  mcPoint->SetPosition(corrExpCoord / 10.);
169  } else
170  mcPoint->SetPosition(pos / 10.); // Convert to cm
171  mcPoint->SetMomentum(mom.Vect() / 1000.); // Convert to GeV/c
172  // mcPoint->Print(nullptr);
173 }
174 
175 void AtSimpleSimulation::RegisterBranch(std::string branchName, bool perc)
176 {
177  auto ioMan = FairRootManager::Instance();
178  if (ioMan == nullptr) {
179  LOG(fatal) << "The IO manager was not instatiated before attempting to simulate an event.";
180  return;
181  }
182 
183  ioMan->Register(branchName.c_str(), "AtTPC", &fMCPoints, perc);
184 }
AtSimpleSimulation::RegisterBranch
void RegisterBranch(std::string branchName="AtTpcPoint", bool pers=true)
Definition: AtSimpleSimulation.cxx:175
AtSimpleSimulation::XYZPoint
ROOT::Math::XYZPoint XYZPoint
Definition: AtSimpleSimulation.h:39
AtSimpleSimulation::fTrackID
static thread_local int fTrackID
Definition: AtSimpleSimulation.h:49
AtSimpleSimulation::ParticleID::A
int A
Definition: AtSimpleSimulation.h:32
AtSimpleSimulation::SimulateParticle
void SimulateParticle(int Z, int A, const XYZPoint &iniPos, const PxPyPzEVector &iniMom)
Definition: AtSimpleSimulation.cxx:92
AtSimpleSimulation.h
AtSimpleSimulation::GetVolume
TGeoVolume * GetVolume(const XYZPoint &pos)
Takes position in mm.
Definition: AtSimpleSimulation.cxx:49
AtSimpleSimulation::AddModel
void AddModel(int Z, int A, ModelPtr model)
Definition: AtSimpleSimulation.cxx:82
node
Definition: fastcluster_dm.cxx:213
AtSimpleSimulation::ParticleID::Z
int Z
Definition: AtSimpleSimulation.h:33
AtSimpleSimulation::NewEvent
void NewEvent()
Definition: AtSimpleSimulation.cxx:141
AtSpaceChargeModel.h
AtMCPoint::SetVolName
void SetVolName(TString VolName)
Definition: AtMCPoint.h:75
AtSimpleSimulation::GetVolumeName
std::string GetVolumeName(const XYZPoint &point)
Definition: AtSimpleSimulation.cxx:73
AtSimpleSimulation::AtSimpleSimulation
AtSimpleSimulation()
Definition: AtSimpleSimulation.cxx:31
AtSimpleSimulation::ParticleID::operator<
bool operator<(const ParticleID &other) const
Definition: AtSimpleSimulation.cxx:37
AtSimpleSimulation::fSCModel
SpaceChargeModel fSCModel
Definition: AtSimpleSimulation.h:44
AtMCPoint.h
AtSimpleSimulation::fGeoMutex
std::mutex fGeoMutex
Definition: AtSimpleSimulation.h:46
AtMCPoint
Definition: AtMCPoint.h:26
AtSimpleSimulation::ModelPtr
std::shared_ptr< AtTools::AtELossModel > ModelPtr
Definition: AtSimpleSimulation.h:38
AtSimpleSimulation::PxPyPzEVector
ROOT::Math::PxPyPzEVector PxPyPzEVector
Definition: AtSimpleSimulation.h:41
AtELossModel.h
AtSimpleSimulation::ParticleID
Definition: AtSimpleSimulation.h:31
AtSimpleSimulation::fDistStep
double fDistStep
Definition: AtSimpleSimulation.h:45
AtSimpleSimulation::IsInVolume
bool IsInVolume(const std::string &volName, const XYZPoint &point)
Definition: AtSimpleSimulation.cxx:62
AtSimpleSimulation::fMCPoints
static thread_local TClonesArray fMCPoints
Definition: AtSimpleSimulation.h:50
AtSimpleSimulation::AddHit
void AddHit(double ELoss, const XYZPoint &pos, const PxPyPzEVector &mom, double length)
Definition: AtSimpleSimulation.cxx:150
AtSimpleSimulation::fModels
std::map< ParticleID, ModelPtr > fModels
Definition: AtSimpleSimulation.h:43