ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HadrontherapyLet.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file HadrontherapyLet.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 // Hadrontherapy advanced example for Geant4
27 // See more at: https://twiki.cern.ch/twiki/bin/view/Geant4/AdvancedExamplesHadrontherapy
28 
30 #include "HadrontherapyLet.hh"
31 
32 #include "HadrontherapyMatrix.hh"
35 #include "HadrontherapyMatrix.hh"
36 #include "G4RunManager.hh"
37 #include "G4SystemOfUnits.hh"
38 #include <cmath>
39 
42 
44 {
45  if (instance) delete instance;
46  instance = new HadrontherapyLet(pDet);
47  return instance;
48 }
49 
51 {
52  return instance;
53 }
54 
56 :filename("Let.out"),matrix(0) // Default output filename
57 {
58 
60 
61  if (!matrix)
62  G4Exception("HadrontherapyLet::HadrontherapyLet",
63  "Hadrontherapy0005", FatalException,
64  "HadrontherapyMatrix not found. Firstly create an instance of it.");
65 
66  nVoxels = matrix -> GetNvoxel();
67 
68  numberOfVoxelAlongX = matrix -> GetNumberOfVoxelAlongX();
69  numberOfVoxelAlongY = matrix -> GetNumberOfVoxelAlongY();
70  numberOfVoxelAlongZ = matrix -> GetNumberOfVoxelAlongZ();
71 
73  pPGA = (HadrontherapyPrimaryGeneratorAction*)runManager -> GetUserPrimaryGeneratorAction();
74  // Pointer to the detector material
75  detectorMat = pDet -> GetDetectorLogicalVolume() -> GetMaterial();
76  density = detectorMat -> GetDensity();
77  // Instances for Total LET
78  totalLetD = new G4double[nVoxels];
80  totalLetT = new G4double[nVoxels];
82 
83 }
84 
86 {
87  Clear();
88  delete [] totalLetD;
89  delete [] DtotalLetD;
90  delete [] totalLetT;
91  delete [] DtotalLetT;
92 }
93 
94 // Fill energy spectrum for every voxel (local energy spectrum)
96 {
97  for(G4int v=0; v < nVoxels; v++) totalLetD[v] = DtotalLetD[v] = totalLetT[v] = DtotalLetT[v] = 0.;
98  Clear();
99 }
104 {
105  for (size_t i=0; i < ionLetStore.size(); i++)
106  {
107  delete [] ionLetStore[i].letDN; // Let Dose Numerator
108  delete [] ionLetStore[i].letDD; // Let Dose Denominator
109  delete [] ionLetStore[i].letTN; // Let Track Numerator
110  delete [] ionLetStore[i].letTD; // Let Track Denominator
111  }
112  ionLetStore.clear();
113 }
115  G4ParticleDefinition* particleDef,
116  G4double ekinMean,
117  G4Material* mat,
118  G4double DE,
119  G4double DEEletrons,
120  G4double DX,
121  G4int i, G4int j, G4int k)
122 {
123  if (DE <= 0. || DX <=0. ) return; // calculate only energy deposit
124  if (!doCalculation) return;
125 
126  // atomic number
127  G4int Z = particleDef -> GetAtomicNumber();
128  if (Z<1) return; // calculate only protons and ions
129 
130  G4int PDGencoding = particleDef -> GetPDGEncoding();
131  PDGencoding -= PDGencoding%10; // simple Particle data group id without excitation level
132 
133  G4int voxel = matrix -> Index(i,j,k);
134 
135  // ICRU stopping power calculation
136  G4EmCalculator emCal;
137  // use the mean kinetic energy of ions in a step to calculate ICRU stopping power
138  G4double Lsn = emCal.ComputeElectronicDEDX(ekinMean, particleDef, mat);
139 
140 
141  // Total LET calculation...
142  totalLetD[voxel] += (DE + DEEletrons) * Lsn; // total dose Let Numerator, including secondary electrons energy deposit
143  DtotalLetD[voxel] += DE + DEEletrons; // total dose Let Denominator, including secondary electrons energy deposit
144  totalLetT[voxel] += DX * Lsn; // total track Let Numerator
145  DtotalLetT[voxel] += DX; // total track Let Denominator
146 
147  // store primary ions and secondary ions
148  size_t l;
149  for (l=0; l < ionLetStore.size(); l++)
150  {
151  // judge species of the current particle and store it
152  if (ionLetStore[l].PDGencoding == PDGencoding)
153  if ( ((trackID ==1) && (ionLetStore[l].isPrimary)) || ((trackID !=1) && (!ionLetStore[l].isPrimary)))
154  break;
155  }
156 
157  if (l == ionLetStore.size()) // Just another type of ion/particle for our store...
158  {
159  // mass number
160  G4int A = particleDef -> GetAtomicMass();
161 
162  // particle name
163  G4String fullName = particleDef -> GetParticleName();
164  G4String name = fullName.substr (0, fullName.find("[") ); // cut excitation energy [x.y]
165 
166  ionLet ion =
167  {
168  (trackID == 1) ? true:false, // is it the primary particle?
169  PDGencoding,
170  fullName,
171  name,
172  Z,
173  A,
174  new G4double[nVoxels], // Let Dose Numerator
175  new G4double[nVoxels], // Let Dose Denominator
176  new G4double[nVoxels], // Let Track Numerator
177  new G4double[nVoxels], // Let Track Denominator
178  };
179 
180  // Initialize let and other parameters
181  for(G4int v=0; v < nVoxels; v++)
182  {
183  ion.letDN[v] = ion.letDD[v] = ion.letTN[v] = ion.letTD[v] = 0.;
184  }
185 
186 
187  ionLetStore.push_back(ion);
188  }
189 
190  // calculate ions let and store them
191  ionLetStore[l].letDN[voxel] += (DE + DEEletrons)* Lsn; // ions dose Let Numerator, including secondary electrons energy deposit
192  ionLetStore[l].letDD[voxel] += DE + DEEletrons; // ions dose Let Denominator, including secondary electrons energy deposit
193  ionLetStore[l].letTN[voxel] += DX* Lsn; // ions track Let Numerator
194  ionLetStore[l].letTD[voxel] += DX; // ions track Let Denominator
195 
196 }
197 
198 
199 
200 
202 {
203  for(G4int v=0; v < nVoxels; v++)
204  {
205  // compute total let
206  if (DtotalLetD[v]>0.) totalLetD[v] = totalLetD[v]/DtotalLetD[v];
207  if (DtotalLetT[v]>0.) totalLetT[v] = totalLetT[v]/DtotalLetT[v];
208  }
209 
210  // Sort ions by A and then by Z ...
211  std::sort(ionLetStore.begin(), ionLetStore.end());
212 
213 
214  // Compute Let Track and Let Dose for ions
215 
216  for(G4int v=0; v < nVoxels; v++)
217  {
218 
219  for (size_t ion=0; ion < ionLetStore.size(); ion++)
220  {
221  // compute ions let
222  if (ionLetStore[ion].letDD[v] >0.) ionLetStore[ion].letDN[v] = ionLetStore[ion].letDN[v] / ionLetStore[ion].letDD[v];
223  if (ionLetStore[ion].letTD[v] >0.) ionLetStore[ion].letTN[v] = ionLetStore[ion].letTN[v] / ionLetStore[ion].letTD[v];
224  } // end loop over ions
225  }
226 } // end loop over voxels
227 
228 
229 
231 {
232 #define width 15L
233 
234  if(ionLetStore.size())
235  {
236  ofs.open(filename, std::ios::out);
237  if (ofs.is_open())
238  {
239 
240  // Write the voxels index and total Lets and the list of particles/ions
241  ofs << std::setprecision(6) << std::left <<
242  "i\tj\tk\t";
243  ofs << std::setw(width) << "LDT";
244  ofs << std::setw(width) << "LTT";
245 
246  for (size_t l=0; l < ionLetStore.size(); l++) // write ions name
247  {
248  G4String a = (ionLetStore[l].isPrimary) ? "_1_D":"_D";
249  ofs << std::setw(width) << ionLetStore[l].name + a ;
250  G4String b = (ionLetStore[l].isPrimary) ? "_1_T":"_T";
251  ofs << std::setw(width) << ionLetStore[l].name + b ;
252  }
253  ofs << G4endl;
254 
255  // Write data
256 
257  G4AnalysisManager* LetFragmentTuple = G4AnalysisManager::Instance();
258 
259  LetFragmentTuple->SetVerboseLevel(1);
260  LetFragmentTuple->SetFirstHistoId(1);
261  LetFragmentTuple->SetFirstNtupleId(1);
262  LetFragmentTuple ->OpenFile("Let");
263 
264 
265  LetFragmentTuple ->CreateNtuple("coordinate", "Let");
266 
267 
268  LetFragmentTuple ->CreateNtupleIColumn("i");//0
269  LetFragmentTuple ->CreateNtupleIColumn("j");//1
270  LetFragmentTuple ->CreateNtupleIColumn("k");//2
271  LetFragmentTuple ->CreateNtupleDColumn("TotalLetD");//3
272  LetFragmentTuple ->CreateNtupleDColumn("TotalLetT");//4
273  LetFragmentTuple ->CreateNtupleIColumn("A");//5
274  LetFragmentTuple ->CreateNtupleIColumn("Z");//6
275  LetFragmentTuple ->CreateNtupleDColumn("IonLETD");//7
276  LetFragmentTuple ->CreateNtupleDColumn("IonLETT");//8
277  LetFragmentTuple ->FinishNtuple();
278 
279 
280  for(G4int i = 0; i < numberOfVoxelAlongX; i++)
281  for(G4int j = 0; j < numberOfVoxelAlongY; j++)
282  for(G4int k = 0; k < numberOfVoxelAlongZ; k++)
283  {
284  LetFragmentTuple->FillNtupleIColumn(1,0, i);
285  LetFragmentTuple->FillNtupleIColumn(1,1, j);
286  LetFragmentTuple->FillNtupleIColumn(1,2, k);
287 
288  G4int v = matrix -> Index(i, j, k);
289 
290  // write total Lets and voxels index
291  ofs << G4endl;
292  ofs << i << '\t' << j << '\t' << k << '\t';
293  ofs << std::setw(width) << totalLetD[v]/(keV/um);
294  ofs << std::setw(width) << totalLetT[v]/(keV/um);
295 
296 
297  // write ions Lets
298  for (size_t l=0; l < ionLetStore.size(); l++)
299  {
300 
301  // Write only not identically null data line
302  if(ionLetStore[l].letDN)
303  {
304  // write ions Lets
305  ofs << std::setw(width) << ionLetStore[l].letDN[v]/(keV/um) ;
306  ofs << std::setw(width) << ionLetStore[l].letTN[v]/(keV/um);
307  }
308  }
309 
310  LetFragmentTuple->FillNtupleDColumn(1,3, totalLetD[v]/(keV/um));
311  LetFragmentTuple->FillNtupleDColumn(1,4, totalLetT[v]/(keV/um));
312 
313 
314  for (size_t ll=0; ll < ionLetStore.size(); ll++)
315  {
316 
317 
318  LetFragmentTuple->FillNtupleIColumn(1,5, ionLetStore[ll].A);
319  LetFragmentTuple->FillNtupleIColumn(1,6, ionLetStore[ll].Z);
320 
321 
322  LetFragmentTuple->FillNtupleDColumn(1,7, ionLetStore[ll].letDN[v]/(keV/um));
323  LetFragmentTuple->FillNtupleDColumn(1,8, ionLetStore[ll].letTN[v]/(keV/um));
324  LetFragmentTuple->AddNtupleRow(1);
325  }
326  }
327  ofs.close();
328 
329  LetFragmentTuple->Write();
330  LetFragmentTuple->CloseFile();
331  }
332 
333  }
334 
335 }
336