ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HadrontherapyRBE.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file HadrontherapyRBE.cc
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 
27 #include "HadrontherapyRBE.hh"
28 #include "HadrontherapyMatrix.hh"
29 
30 #include "G4UnitsTable.hh"
31 #include "G4SystemOfUnits.hh"
32 #include "G4GenericMessenger.hh"
33 #include "G4Pow.hh"
34 
35 #include <fstream>
36 #include <iostream>
37 #include <iomanip>
38 #include <cstdlib>
39 #include <algorithm>
40 #include <sstream>
41 #include <numeric>
42 
43 #define width 15L
44 
45 using namespace std;
46 
47 // TODO: Perhaps we can use the material database???
48 const std::map<G4String, G4int> elements = {
49  {"H", 1},
50  {"He", 2},
51  {"Li", 3},
52  {"Be", 4},
53  {"B", 5},
54  {"C", 6},
55  {"N", 7},
56  {"O", 8},
57  {"F", 9},
58  {"Ne", 10}
59 };
60 
62 
64 {
65  return instance;
66 }
67 
69 {
70  if (instance) delete instance;
71  instance = new HadrontherapyRBE(voxelX, voxelY, voxelZ, massOfVoxel);
72  return instance;
73 }
74 
75 HadrontherapyRBE::HadrontherapyRBE(G4int voxelX, G4int voxelY, G4int voxelZ, G4double massOfVoxel)
76  : fNumberOfVoxelsAlongX(voxelX),
77  fNumberOfVoxelsAlongY(voxelY),
78  fNumberOfVoxelsAlongZ(voxelZ),
79  fNumberOfVoxels(voxelX * voxelY * voxelY),
80  fMassOfVoxel(massOfVoxel)
81 
82 {
84 
85  // x axis for 1-D plot
86  // TODO: Remove
88 
89  for (G4int i = 0; i < fNumberOfVoxelsAlongX; i++)
90  {
91  x[i] = 0;
92  }
93 
94 }
95 
97 {
98  delete[] x;
99  delete fMessenger;
100 }
101 
103 {
104  G4cout << "RBE Cell line: " << fActiveCellLine << G4endl;
105  G4cout << "RBE Dose threshold value: " << fDoseCut / gray << " gray" << G4endl;
106  G4cout << "RBE Alpha X value: " << fAlphaX * gray << " 1/gray" << G4endl;
107  G4cout << "RBE Beta X value: " << fBetaX * pow(gray, 2.0) << " 1/gray2" << G4endl;
108 }
109 
120 vector<G4String> split(const G4String& line, const G4String& delimiter)
121 {
122  vector<G4String> result;
123 
124  size_t current = 0;
125  size_t pos = 0;
126 
127  while(pos != G4String::npos)
128  {
129  pos = line.find(delimiter, current);
130  G4String token = line.substr(current, pos - current);
131  token = token.strip(G4String::both);
132  token = token.strip(G4String::both, '\"');
133  result.push_back(token);
134  current = pos + delimiter.size();
135  }
136  return result;
137 }
138 
140 {
141  // TODO: Check for presence? Perhaps we want to be able to load more
142 
143  ifstream in(path);
144  if (!in)
145  {
146  stringstream ss;
147  ss << "Cannot open LEM table input file: " << path;
148  G4Exception("HadrontherapyRBE::LoadData", "WrongTable", FatalException, ss.str().c_str());
149  }
150 
151  // Start with the first line
152  G4String line;
153  if (!getline(in, line))
154  {
155  stringstream ss;
156  ss << "Cannot read header from the LEM table file: " << path;
157  G4Exception("HadrontherapyRBE::LoadLEMTable", "CannotReadHeader", FatalException, ss.str().c_str());
158  }
159  vector<G4String> header = split(line, ",");
160 
161  // Find the order of columns
162  std::vector<G4String> columns = { "alpha_x", "beta_x", "D_t", "specific_energy", "alpha", "beta", "cell", "particle"};
163  std::map<G4String, int> columnIndices;
164  for (auto columnName : columns)
165  {
166  auto pos = find(header.begin(), header.end(), columnName);
167  if (pos == header.end())
168  {
169  stringstream ss;
170  ss << "Column " << columnName << " not present in the LEM table file.";
171  G4Exception("HadrontherapyRBE::LoadLEMTable", "ColumnNotPresent", FatalException, ss.str().c_str());
172  }
173  else
174  {
175  columnIndices[columnName] = distance(header.begin(), pos);
176  }
177  }
178 
179  // Continue line by line
180  while (getline(in, line))
181  {
182  vector<G4String> lineParts = split(line, ",");
183  G4String cellLine = lineParts[columnIndices["cell"]];
184  G4int element = elements.at(lineParts[columnIndices["particle"]]);
185 
186  fTablesEnergy[cellLine][element].push_back(
187  stod(lineParts[columnIndices["specific_energy"]]) * MeV
188  );
189  fTablesAlpha[cellLine][element].push_back(
190  stod(lineParts[columnIndices["alpha"]])
191  );
192  /* fTablesLet[cellLine][element].push_back(
193  stod(lineParts[columnIndices["let"]])
194  ); */
195  fTablesBeta[cellLine][element].push_back(
196  stod(lineParts[columnIndices["beta"]])
197  );
198 
199  fTablesAlphaX[cellLine] = stod(lineParts[columnIndices["alpha_x"]]) / gray;
200  fTablesBetaX[cellLine] = stod(lineParts[columnIndices["beta_x"]]) / (gray * gray);
201  fTablesDoseCut[cellLine] = stod(lineParts[columnIndices["D_t"]]) * gray;
202  }
203 
204  // Sort the tables by energy
205  // (https://stackoverflow.com/a/12399290/2692780)
206  for (auto aPair : fTablesEnergy)
207  {
208  for (auto ePair : aPair.second)
209  {
210  vector<G4double>& tableEnergy = fTablesEnergy[aPair.first][ePair.first];
211  vector<G4double>& tableAlpha = fTablesAlpha[aPair.first][ePair.first];
212  vector<G4double>& tableBeta = fTablesBeta[aPair.first][ePair.first];
213 
214  vector<size_t> idx(tableEnergy.size());
215  iota(idx.begin(), idx.end(), 0);
216  sort(idx.begin(), idx.end(),
217  [&tableEnergy](size_t i1, size_t i2) {return tableEnergy[i1] < tableEnergy[i2];});
218 
219  vector<vector<G4double>*> tables = {
220  &tableEnergy, &tableAlpha, &tableBeta
221  };
222  for (vector<G4double>* table : tables)
223  {
224  vector<G4double> copy = *table;
225  for (size_t i = 0; i < copy.size(); ++i)
226  {
227  (*table)[i] = copy[idx[i]];
228  }
229  // G4cout << (*table)[0];
230  // reorder(*table, idx);
231  G4cout << (*table)[0] << G4endl;
232  }
233  }
234  }
235 
236  if (fVerboseLevel > 0)
237  {
238  G4cout << "RBE: read LEM data for the following cell lines and elements [number of points]: " << G4endl;
239  for (auto aPair : fTablesEnergy)
240  {
241  G4cout << "- " << aPair.first << ": ";
242  for (auto ePair : aPair.second)
243  {
244  G4cout << ePair.first << "[" << ePair.second.size() << "] ";
245  }
246  G4cout << G4endl;
247  }
248  }
249 }
250 
252 {
253  if (fTablesEnergy.size() == 0)
254  {
255  G4Exception("HadrontherapyRBE::SetCellLine", "NoCellLine", FatalException, "Cannot select cell line, probably LEM table not loaded yet?");
256  }
257  if (fTablesEnergy.find(name) == fTablesEnergy.end())
258  {
259  stringstream str;
260  str << "Cell line " << name << " not found in the LEM table.";
261  G4Exception("HadrontherapyRBE::SetCellLine", "", FatalException, str.str().c_str());
262  }
263  else
264  {
268 
272 
273  fMinZ = 0;
274  fMaxZ = 0;
275  fMinEnergies.clear();
276  fMaxEnergies.clear();
277 
278  for (auto energyPair : *fActiveTableEnergy)
279  {
280  if (!fMinZ || (energyPair.first < fMinZ)) fMinZ = energyPair.first;
281  if (energyPair.first > fMaxZ) fMaxZ = energyPair.first;
282 
283  fMinEnergies[energyPair.first] = energyPair.second[0];
284  fMaxEnergies[energyPair.first] = energyPair.second[energyPair.second.size() - 1];
285  }
286  }
287 
289 
290  if (fVerboseLevel > 0)
291  {
292  G4cout << "RBE: cell line " << name << " selected." << G4endl;
293  }
294 }
295 
296 std::tuple<G4double, G4double> HadrontherapyRBE::GetHitAlphaAndBeta(G4double E, G4int Z)
297 {
298  if (!fActiveTableEnergy)
299  {
300  G4Exception("HadrontherapyRBE::GetHitAlphaAndBeta", "NoCellLine", FatalException, "No cell line selected. Please, do it using the /rbe/cellLine command.");
301  }
302 
303  // Check we are in the tables
304  if ((Z < fMinZ) || (Z > fMaxZ))
305  {
306  if (fVerboseLevel > 1)
307  {
308  stringstream str;
309  str << "Alpha & beta calculation supported only for ";
310  str << fMinZ << " <= Z <= " << fMaxZ << ", but " << Z << " requested.";
311  G4Exception("HadrontherapyRBE::GetHitAlphaAndBeta", "", JustWarning, str.str().c_str());
312  }
313  return make_tuple<G4double, G4double>( 0.0, 0.0 ); //out of table!
314  }
315  if ((E < fMinEnergies[Z]) || (E >= fMaxEnergies[Z]))
316  {
317  if (fVerboseLevel > 2)
318  {
319  G4cout << "RBE hit: Z=" << Z << ", E=" << E << " => out of LEM table";
320  if (fVerboseLevel > 3)
321  {
322  G4cout << " (" << fMinEnergies[Z] << " to " << fMaxEnergies[Z] << " MeV)";
323  }
324  G4cout << G4endl;
325  }
326  return make_tuple<G4double, G4double>( 0.0, 0.0 ); //out of table!
327  }
328 
329  std::vector<G4double>& vecEnergy = (*fActiveTableEnergy)[Z];
330  std::vector<G4double>& vecAlpha = (*fActiveTableAlpha)[Z];
331  std::vector<G4double>& vecBeta = (*fActiveTableBeta)[Z];
332 
333  // Find the row in energy tables
334  const auto eLarger = upper_bound(begin(vecEnergy), end(vecEnergy), E);
335  const G4int lower = distance(begin(vecEnergy), eLarger) - 1;
336  const G4int upper = lower + 1;
337 
338  // Interpolation
339  const G4double energyLower = vecEnergy[lower];
340  const G4double energyUpper = vecEnergy[upper];
341  const G4double energyFraction = (E - energyLower) / (energyUpper - energyLower);
342 
343  //linear interpolation along E
344  const G4double alpha = ((1 - energyFraction) * vecAlpha[lower] + energyFraction * vecAlpha[upper]);
345  const G4double beta = ((1 - energyFraction) * vecBeta[lower] + energyFraction * vecBeta[upper]);
346  if (fVerboseLevel > 2)
347  {
348  G4cout << "RBE hit: Z=" << Z << ", E=" << E << " => alpha=" << alpha << ", beta=" << beta << G4endl;
349  }
350 
351  return make_tuple(alpha, beta);
352 }
353 
354 // Zaider & Rossi alpha & Beta mean
356 {
357  if (fVerboseLevel > 0)
358  {
359  G4cout << "RBE: Computing alpha and beta..." << G4endl;
360  }
362 
363  fBeta = pow(fBetaNumerator / fDenominator * gray, 2.0);
364 
365  //g4pow -> powN(fBetaNumerator / fDenominator * gray, 2)
366 }
367 
369 {
370  if (fVerboseLevel > 0)
371  {
372  G4cout << "RBE: Computing survival and RBE..." << G4endl;
373  }
374  G4double smax = fAlphaX + 2 * fBetaX * fDoseCut;
375 
376  // Prepare matrices that were not initialized yet
377  fLnS.resize(fNumberOfVoxels);
378  fDoseX.resize(fNumberOfVoxels);
379 
380  for (G4int i = 0; i < fNumberOfVoxels; i++)
381  {
382  if (std::isnan(fAlpha[i]) || std::isnan(fBeta[i]))
383  {
384  fLnS[i] = 0.0;
385  fDoseX[i] = 0.0;
386  }
387  else if (fDose[i] <= fDoseCut)
388  {
389  fLnS[i] = -(fAlpha[i] * fDose[i]) - (fBeta[i] * (pow(fDose[i], 2.0))) ;
390  fDoseX[i] = sqrt((-fLnS[i] / fBetaX) + pow((fAlphaX / (2 * fBetaX)), 2.0)) - (fAlphaX / (2 * fBetaX));
391  }
392  else
393  {
394  G4double ln_Scut = -(fAlpha[i] * fDoseCut) - (fBeta[i] * (pow((fDoseCut), 2.0)));
395  fLnS[i] = ln_Scut - ((fDose[i] - fDoseCut) * smax);
396 
397  // TODO: CHECK THIS!!!
398  fDoseX[i] = ( (-fLnS[i] + ln_Scut) / smax ) + fDoseCut;
399  }
400  }
401  fRBE = fDoseX / fDose;
402  fSurvival = exp(fLnS);
403 }
404 
406 {
407  if (fVerboseLevel > 1)
408  {
409  G4cout << "RBE: Setting denominator..." << G4endl;
410  }
412 }
413 
415 {
416  if (fVerboseLevel > 1)
417  {
418  G4cout << "RBE: Adding denominator...";
419  }
420  if (fDenominator.size())
421  {
422  fDenominator += denom;
423  }
424  else
425  {
426  if (fVerboseLevel > 1)
427  {
428  G4cout << " (created empty array)";
429  }
431  }
432  G4cout << G4endl;
433 }
434 
436 {
437  if (fVerboseLevel > 1)
438  {
439  G4cout << "RBE: Setting alpha numerator..." << G4endl;
440  }
442 }
443 
445 {
446  if (fVerboseLevel > 1)
447  {
448  G4cout << "RBE: Setting beta numerator..." << G4endl;
449  }
450  fBetaNumerator = beta;
451 }
452 
454 {
455  if (fVerboseLevel > 1)
456  {
457  G4cout << "RBE: Adding alpha numerator...";
458  }
459  if (fAlphaNumerator.size())
460  {
462  }
463  else
464  {
465  if (fVerboseLevel > 1)
466  {
467  G4cout << " (created empty array)";
468  }
470  }
471  G4cout << G4endl;
472 }
473 
475 {
476  if (fVerboseLevel > 1)
477  {
478  G4cout << "RBE: Adding beta...";
479  }
480  if (fBetaNumerator.size())
481  {
482  fBetaNumerator += beta;
483  }
484  else
485  {
486  if (fVerboseLevel > 1)
487  {
488  G4cout << " (created empty array)";
489  }
490  fBetaNumerator = beta;
491  }
492  G4cout << G4endl;
493 }
494 
495 void HadrontherapyRBE::SetEnergyDeposit(const std::valarray<G4double> eDep)
496 {
497  if (fVerboseLevel > 1)
498  {
499  G4cout << "RBE: Setting dose..." << G4endl;
500  }
501  fDose = eDep * (fDoseScale / fMassOfVoxel);
502 }
503 
504 void HadrontherapyRBE::AddEnergyDeposit(const std::valarray<G4double> eDep)
505 {
506  if (fVerboseLevel > 1)
507  {
508  G4cout << "RBE: Adding dose... (" << eDep.size() << " points)" << G4endl;
509  }
510  if (fDose.size())
511  {
512  fDose += eDep * (fDoseScale / fMassOfVoxel);
513  }
514  else
515  {
516  if (fVerboseLevel > 1)
517  {
518  G4cout << " (created empty array)";
519  }
520  fDose = eDep * (fDoseScale / fMassOfVoxel);
521  }
522 }
523 
525 {
526  if (fVerboseLevel > 1)
527  {
528  G4cout << "RBE: Writing alpha and beta..." << G4endl;
529  }
530  ofstream ofs(fAlphaBetaPath);
531 
533 
534  if (ofs.is_open())
535  {
536  ofs << "alpha" << std::setw(width) << "beta " << std::setw(width) << "depth(slice)" << G4endl;
538  ofs << fAlpha[i]*gray << std::setw(15L) << fBeta[i]*pow(gray, 2.0) << std::setw(15L) << i << G4endl;
539  }
540  if (fVerboseLevel > 0)
541  {
542  G4cout << "RBE: Alpha and beta written to " << fAlphaBetaPath << G4endl;
543  }
544 }
545 
547 {
548  ofstream ofs(fRBEPath);
549 
550  // TODO: only if not yet calculated. Or in RunAction???
551  ComputeRBE();
552 
553  if (ofs.is_open())
554  {
555  ofs << "Dose(Gy)" << std::setw(width) << "ln(S) " << std::setw(width) << "Survival" << std::setw(width) << "DoseB(Gy)" << std::setw(width) << "RBE" << std::setw(width) << "depth(slice)" << G4endl;
556 
558 
559  ofs << (fDose[i] / gray) << std::setw(width) << fLnS[i] << std::setw(width) << fSurvival[i]
560  << std::setw(width) << fDoseX[i] / gray << std::setw(width) << fRBE[i] << std::setw(width) << i << G4endl;
561  }
562  if (fVerboseLevel > 0)
563  {
564  G4cout << "RBE: RBE written to " << fRBEPath << G4endl;
565  }
566 }
567 
569 {
570  if (fVerboseLevel > 1)
571  {
572  G4cout << "RBE: Reset(): ";
573  }
574  fAlphaNumerator = 0.0;
575  fBetaNumerator = 0.0;
576  fDenominator = 0.0;
577  fDose = 0.0;
578  if (fVerboseLevel > 1)
579  {
580  G4cout << fAlphaNumerator.size() << " points." << G4endl;
581  }
582 }
583 
585 {
586  fMessenger = new G4GenericMessenger(this, "/rbe/");
587  fMessenger->SetGuidance("RBE calculation");
588 
590  .SetGuidance("Whether to enable RBE calculation")
592  .SetToBeBroadcasted(false);
593 
595  .SetGuidance("Set verbosity level of RBE")
596  .SetGuidance("0 = quiet")
597  .SetGuidance("1 = important messages (~10 per run)")
598  .SetGuidance("2 = debug")
599  .SetToBeBroadcasted(false);
600 
602  .SetGuidance("Load a LEM table used in calculating alpha&beta")
604  .SetToBeBroadcasted(false);
605 
607  .SetGuidance("Set the cell line for alpha&beta calculation")
609  .SetToBeBroadcasted(false);
610 
612  .SetGuidance("Set the scaling factor to calculate RBE with the real physical dose")
613  .SetGuidance("If you don't set this, the RBE will be incorrect")
615  .SetToBeBroadcasted(false);
616 
618  .SetGuidance("If false, reset the values at the beginning of each run.")
619  .SetGuidance("If true, all runs are summed together")
621  .SetToBeBroadcasted(false);
622 
624  .SetGuidance("Reset accumulated data (relevant only if accumulate mode is on)")
626  .SetToBeBroadcasted(false);
627 }
628 
629 /*
630 G4bool HadrontherapyRBE::LinearLookup(G4double E, G4double LET, G4int Z)
631 {
632  G4int j;
633  G4int indexE;
634  if ( E < vecEnergy[0] || E >= vecEnergy[GetRowVecEnergy() - 1]) return false; //out of table!
635 
636  // Search E
637  for (j = 0; j < GetRowVecEnergy(); j++)
638  {
639  if (j + 1 == GetRowVecEnergy()) break;
640  if (E >= vecEnergy[j] && E < vecEnergy[j + 1]) break;
641  }
642 
643  indexE = j;
644 
645  G4int k = (indexE * column);
646 
647  G4int l = ((indexE + 1) * column);
648 
649  if (Z <= 8) //linear interpolation along E for calculate alpha and beta
650  {
651  interpolation_onE(k, l, indexE, E, Z);
652  }
653  else
654  {
655 
656  return interpolation_onLET1_onLET2_onE(k, l, indexE, E, LET);
657 
658  }
659  return true;
660 }
661 */
662 
663 /*
664 void HadrontherapyRBE::interpolation_onE(G4int k, G4int l, G4int indexE, G4double E, G4int Z)
665 {
666  // k=(indexE*column) identifies the position of E1 known the value of E (identifies the group of 8 elements in the array at position E1)
667  // Z-1 identifies the vector ion position relative to the group of 8 values ​​found
668 
669  k = k + (Z - 1);
670  l = l + (Z - 1);
671 
672  //linear interpolation along E
673  alpha = (((vecEnergy[indexE + 1] - E) / (vecEnergy[indexE + 1] - vecEnergy[indexE])) * vecAlpha[k]) + ((E - vecEnergy[indexE]) / (vecEnergy[indexE + 1] - vecEnergy[indexE])) * vecAlpha[l];
674 
675  beta = (((vecEnergy[indexE + 1] - E) / (vecEnergy[indexE + 1] - vecEnergy[indexE])) * vecBeta[k]) + ((E - vecEnergy[indexE]) / (vecEnergy[indexE + 1] - vecEnergy[indexE])) * vecBeta[l];
676 
677 }
678 
679 G4bool HadrontherapyRBE::interpolation_onLET1_onLET2_onE(G4int k, G4int l, G4int indexE, G4double E, G4double LET)
680 {
681  G4double LET1_2, LET3_4, LET1_2_beta, LET3_4_beta;
682  G4int indexLET1, indexLET2, indexLET3, indexLET4;
683  size_t i;
684  if ( (LET >= vecLET[k + column - 1] && LET >= vecLET[l + column - 1]) || (LET < vecLET[k] && LET < vecLET[l]) ) return false; //out of table!
685 
686  //Find the value of E1 is detected the value of LET among the 8 possible values ​​corresponding to E1
687  for (i = 0; i < column - 1; i++)
688  {
689 
690  if ( (i + 1 == column - 1) || (LET < vecLET[k]) ) break;
691 
692  else if (LET >= vecLET[k] && LET < vecLET[k + 1]) break;
693  k++;
694 
695  }
696  indexLET1 = k;
697  indexLET2 = k + 1;
698 
699  //Find the value of E2 is detected the value of LET among the 8 possible values ​​corresponding to E2
700  for (i = 0; i < column - 1; i++)
701  {
702 
703  if (i + 1 == column - 1) break;
704  if (LET >= vecLET[l] && LET < vecLET[l + 1]) break; // time to interpolate
705  l++;
706 
707  }
708 
709  indexLET3 = l;
710  indexLET4 = l + 1;
711 
712  //Interpolation between LET1 and LET2 on E2 position
713  LET1_2 = (((vecLET[indexLET2] - LET) / (vecLET[indexLET2] - vecLET[indexLET1])) * vecAlpha[indexLET1]) + ((LET - vecLET[indexLET1]) / (vecLET[indexLET2] - vecLET[indexLET1])) * vecAlpha[indexLET2];
714 
715  LET1_2_beta = (((vecLET[indexLET2] - LET) / (vecLET[indexLET2] - vecLET[indexLET1])) * vecBeta[indexLET1]) + ((LET - vecLET[indexLET1]) / (vecLET[indexLET2] - vecLET[indexLET1])) * vecBeta[indexLET2];
716 
717  //Interpolation between LET3 and LET4 on E2 position
718  LET3_4 = (((vecLET[indexLET4] - LET) / (vecLET[indexLET4] - vecLET[indexLET3])) * vecAlpha[indexLET3]) + ((LET - vecLET[indexLET3]) / (vecLET[indexLET4] - vecLET[indexLET3])) * vecAlpha[indexLET4];
719  LET3_4_beta = (((vecLET[indexLET4] - LET) / (vecLET[indexLET4] - vecLET[indexLET3])) * vecBeta[indexLET3]) + ((LET - vecLET[indexLET3]) / (vecLET[indexLET4] - vecLET[indexLET3])) * vecBeta[indexLET4];
720 
721  //Interpolation along E between LET1_2 and LET3_4
722  alpha = (((vecEnergy[indexE + 1] - E) / (vecEnergy[indexE + 1] - vecEnergy[indexE])) * LET1_2) + ((E - vecEnergy[indexE]) / (vecEnergy[indexE + 1] - vecEnergy[indexE])) * LET3_4;
723  beta = (((vecEnergy[indexE + 1] - E) / (vecEnergy[indexE + 1] - vecEnergy[indexE])) * LET1_2_beta) + ((E - vecEnergy[indexE]) / (vecEnergy[indexE + 1] - vecEnergy[indexE])) * LET3_4_beta;
724 
725 
726  return true;
727 }
728 **/
729 
730 /* void HadrontherapyRBE::SetThresholdValue(G4double dosecut)
731 {
732  fDoseCut = dosecut;
733 }
734 
735 void HadrontherapyRBE::SetAlphaX(G4double alphaX)
736 {
737  fAlphaX = alphaX;
738 }
739 
740 void HadrontherapyRBE::SetBetaX(G4double betaX)
741 {
742  fBetaX = betaX;
743 }*/
744 
746 {
747  fCalculationEnabled = enabled;
748 }
749 
751 {
752  fAccumulate = accumulate;
753  // The accumulation should start now, not taking into account old data
754  Reset();
755 }
756 
757 /*
758 void HadrontherapyRBE::SetLEMTablePath(G4String path)
759 {
760  // fLEMTablePath = path;
761  LoadLEMTable(path);
762 }
763 */
764 
766 {
767  fDoseScale = scale;
768 }
769 
770 // Nearest neighbor interpolation
771 /*
772 G4bool HadrontherapyRBE::NearLookup(G4double E, G4double DE)
773 {
774 
775  size_t j = 0, step = 77;
776 
777  // Check bounds
778  if (E < vecE[0] || E > vecE.back() || DE < vecDE[0] || DE > vecDE[step - 1]) return false; //out of table!
779 
780  // search for Energy... simple linear search. This take approx 1 us per single search on my sempron 2800+ laptop
781  for (; j < vecE.size(); j += step)
782  {
783  if (E <= vecE[j]) break;
784  }
785  if (j == vecE.size()) j -= step;
786  if (j == vecE.size() && E > vecE[j]) return false; // out of table!
787 
788 
789  // find nearest (better interpolate)
790  if ( j > 0 && ((vecE[j] - E) > (E - vecE[j - 1])) ) {j = j - step;}
791  bestE = vecE[j];
792 
793 
794  // search for stopping power... simple linear search
795  for (; vecE[j] == bestE && j < vecE.size(); j++)
796  {
797  if (DE <= vecDE[j]) break;
798  }
799  if (j == vecE.size() && DE > vecDE[j]) return false;// out of table!
800 
801  if (j == 0 && (E < vecE[j] || DE < vecDE[j]) ) return false;// out of table!
802 
803  if ( (vecDE[j] - DE) > (DE - vecDE[j - 1]) ) {j = j - 1;}
804  bestDE = vecDE[j];
805 
806  this -> alpha = vecAlpha[j];
807  this -> beta = vecBeta[j];
808 
809  return true;
810 }
811 */