ATTPCROOT  0.3.0-alpha
A ROOT-based framework for analyzing data from active target detectors
AtELossTable.cxx
Go to the documentation of this file.
1 #include "AtELossTable.h"
2 // IWYU pragma: no_include <ext/alloc_traits.h>
3 #include "AtStringManip.h"
4 
5 #include <FairLogger.h>
6 
7 #include <algorithm> // for max
8 #include <cmath> // for fabs
9 #include <iostream>
10 
11 namespace AtTools {
12 
13 void AtELossTable::LoadTable(const std::vector<double> &energy, const std::vector<double> &dEdX)
14 {
15  if (energy.size() > 0)
16  LOG(info) << "Loading dE/dX from " << energy.front() << " MeV to " << energy.back() << " MeV ";
17  else
18  LOG(error) << "Passed table was empty!";
19 
20  std::vector<double> dXdE;
21  for (auto &elem : dEdX)
22  dXdE.push_back(1 / elem);
23  fdXdE = tk::spline(energy, dXdE);
24 }
25 
26 AtELossTable::AtELossTable(const std::vector<double> &energy, const std::vector<double> &dEdX, double density)
27  : AtELossModel(density)
28 {
29  LoadTable(energy, dEdX);
30 }
31 
32 double AtELossTable::GetdEdx(double energy) const
33 {
34  double dedx = 1 / fdXdE(energy);
35  return dedx * fdEdxScale;
36 }
37 
38 double AtELossTable::GetRange(double energyIni, double energyFin) const
39 {
40  if (energyIni == energyFin)
41  return 0;
42 
43  return fdXdE.integrate(energyFin, energyIni);
44 }
45 
46 double AtELossTable::GetEnergy(double energyIni, double distance) const
47 {
48  if (distance == 0)
49  return energyIni;
50  if (energyIni < 1e-6 || GetRange(energyIni) < distance)
51  return 0.;
52 
53  int maxIt = 100;
54 
55  double guessEnergy = energyIni - GetdEdx(energyIni) * distance;
56  for (int i = 0; i < maxIt; ++i) {
57 
58  double range = GetRange(energyIni, guessEnergy);
59  if (fabs(range - distance) < fDistErr) {
60  LOG(debug) << "Energy converged in " << i + 1 << " iterations.";
61  return guessEnergy;
62  }
63  LOG(debug) << "guessE: " << guessEnergy << " d: " << distance << " R: " << range
64  << " dEdX: " << GetdEdx(guessEnergy) << " dEnergy: " << GetdEdx(guessEnergy) * (distance - range);
65  // Update guess energy using what is essentially Newton's method
66  guessEnergy += GetdEdx(guessEnergy) * (range - distance);
67  }
68 
69  LOG(error) << "Energy calculation (" << energyIni << " MeV through " << distance << " mm) failed to converge in "
70  << maxIt << " iterations!";
71  return -1;
72 }
73 
74 double AtELossTable::GetEnergyOld(double energyIni, double distance) const
75 {
76  if (distance == 0)
77  return energyIni;
78  if (energyIni < 1e-6)
79  return 0.;
80 
81  double maxRange = GetRange(energyIni);
82 
83  if (distance > maxRange)
84  return 0.;
85 
86  // Searcg for energyFinal where GetRange(energyIni, energyFinal) == distance
87 
88  double lowGuess = 0;
89  double highGuess = energyIni;
90  double guessEnergy = energyIni / 2.0;
91  double range = GetRange(energyIni, guessEnergy);
92  double distErr = 1.0e-4; // in mm
93  int numIt = 1;
94 
95  while (fabs(range - distance) > distErr) {
96  numIt++;
97  // We went too far
98  if (range > distance) {
99  lowGuess = guessEnergy;
100  guessEnergy = (lowGuess + highGuess) / 2.0;
101  } else {
102  // We didn't go far enough
103  highGuess = guessEnergy;
104  guessEnergy = (lowGuess + highGuess) / 2.0;
105  }
106  range = GetRange(energyIni, guessEnergy);
107  }
108 
109  LOG(info) << "Energy converged in " << numIt << " iterations.";
110  return guessEnergy;
111 }
112 
113 void AtELossTable::LoadSrimTable(std::string fileName)
114 {
115  std::ifstream file(fileName);
116  if (!file.is_open())
117  LOG(fatal) << "Failed to open SRIM file " << fileName;
118 
119  bool atConversion = false;
120  double conversion = 0;
121  std::vector<double> energy;
122  std::vector<double> dEdX;
123 
124  while (!file.eof()) {
125  // Get the current line
126  std::string line;
127  std::getline(file, line);
128  auto tokens = SplitString(line, ' ');
129  LOG(debug) << "Processing line " << line;
130 
131  // If this is the densityt line, grab it and continue
132  if (tokens[0] == "Target" && tokens[1] == "Density") {
133  LOG(info) << "Setting target density to: " << tokens[3] << " g/cm^3";
134  SetIniDensity(std::stod(tokens[3]));
135  continue;
136  }
137 
138  // Check if we've reached the conversion part of the table
139  atConversion |= (tokens[0] == "Multiply");
140  LOG(debug) << "At converion: " << atConversion;
141 
142  // If we're at the conversion stage, look for the correct conversion factor
143  try {
144  if (atConversion && tokens.at(1) == "MeV" && tokens.at(3) == "mm") {
145  conversion = std::stod(tokens.at(0));
146  LOG(info) << "Using conversion factor of " << conversion;
147  break;
148  }
149 
150  // If this is part of the table, grab it and continue
151  double en = std::stod(tokens.at(0)) * GetUnitConversion(tokens.at(1));
152  double dedx = std::stod(tokens.at(2)) + std::stod(tokens.at(3));
153 
154  // If we made it this far then we have a valid table entry
155  energy.push_back(en);
156  dEdX.push_back(dedx);
157 
158  LOG(debug) << en << " " << dedx;
159 
160  } catch (...) {
161  }
162  } // end loop over file
163 
164  for (auto &dedx : dEdX)
165  dedx *= conversion;
166 
167  LoadTable(energy, dEdX);
168 }
169 
170 void AtELossTable::LoadLiseTable(std::string fileName, double mass, double density, int column)
171 {
172  std::ifstream file(fileName);
173  if (!file.is_open())
174  LOG(fatal) << "Failed to open SRIM file " << fileName;
175 
176  std::vector<double> energy;
177  std::vector<double> dEdX;
178  SetIniDensity(fabs(density));
179 
180  while (!file.eof()) {
181  // Get the current line
182  std::string line;
183  std::getline(file, line);
184  auto tokens = SplitString(line, '\t');
185  LOG(debug) << "Processing line " << line;
186 
187  try {
188  // If this is part of the table, grab it and continue
189  double en = std::stod(tokens.at(0 + column * 2)) * mass;
190  double dedx = std::stod(tokens.at(1 + column * 2));
191 
192  if (density > 0) // dEdX is in units MeV/(mg/cm^2)
193  dedx *= (100 * density);
194  else // dEdX is in units MeV/um
195  dedx *= 1000;
196 
197  LOG(debug) << "En: " << en << " dEdX " << dedx;
198  // If we made it this far then we have a valid table entry
199  energy.push_back(en);
200  dEdX.push_back(dedx);
201  } catch (...) {
202  }
203  }
204 
205  LoadTable(energy, dEdX);
206 }
207 
208 double AtELossTable::GetUnitConversion(const std::string &unit)
209 {
210  if (unit == "eV")
211  return 1e-6;
212  if (unit == "keV")
213  return 1e-3;
214  if (unit == "MeV")
215  return 1e-0;
216  if (unit == "GeV")
217  return 1e3;
218  return 0;
219 }
220 } // namespace AtTools
AtTools::AtELossTable::GetRange
virtual double GetRange(double energyIni, double energyFin=0) const override
Definition: AtELossTable.cxx:38
AtTools::AtELossTable::fDistErr
double fDistErr
Definition: AtELossTable.h:17
AtTools::AtELossTable::GetEnergy
virtual double GetEnergy(double energyIni, double distance) const override
Definition: AtELossTable.cxx:46
AtTools::AtELossTable::LoadSrimTable
void LoadSrimTable(std::string fileName)
Definition: AtELossTable.cxx:113
AtTools::SplitString
std::vector< std::string > SplitString(const std::string &s, char delim)
split string, s, into vector of tokens split by delim.
Definition: AtStringManip.cxx:6
stod
double stod(const char *s)
Definition: util.cxx:20
tk::spline::integrate
double integrate(double x0, double x1) const
Definition: AtSpline.cxx:370
AtTools::AtELossTable::GetEnergyOld
double GetEnergyOld(double energyIni, double distance) const
Definition: AtELossTable.cxx:74
tk::spline
Definition: AtSpline.h:43
AtTools::AtELossTable::AtELossTable
AtELossTable(double density=0)
Definition: AtELossTable.h:20
AtTools
Definition: AtSimpleSimulation.h:19
AtTools::AtELossTable::fdXdE
tk::spline fdXdE
Definition: AtELossTable.h:15
AtTools::AtELossModel::fdEdxScale
double fdEdxScale
Definition: AtELossModel.h:28
AtTools::AtELossModel::SetIniDensity
void SetIniDensity(double density)
Definition: AtELossModel.h:58
AtTools::AtELossTable::LoadLiseTable
void LoadLiseTable(std::string fileName, double mass, double density, int column=2)
Definition: AtELossTable.cxx:170
AtTools::AtELossTable::GetdEdx
virtual double GetdEdx(double energy) const override
Definition: AtELossTable.cxx:32
AtELossTable.h
AtTools::AtELossModel
Definition: AtELossModel.h:15
AtStringManip.h