Geant4  10.01.p03
HadrontherapyMatrix.cc
Go to the documentation of this file.
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 // Visit the Hadrontherapy web site (http://www.lns.infn.it/link/Hadrontherapy) to request
26 // the *COMPLETE* version of this program, together with its documentation;
27 // Hadrontherapy (both basic and full version) are supported by the Italian INFN
28 // Institute in the framework of the MC-INFN Group
29 //
30 
31 #include <fstream>
32 #include <iostream>
33 #include <sstream>
34 #include <iomanip>
35 
36 #include "HadrontherapyMatrix.hh"
39 #include "globals.hh"
40 #include "G4SystemOfUnits.hh"
41 #include "G4RunManager.hh"
42 #include "G4ParticleGun.hh"
43 
44 // Units definition: CLHEP/Units/SystemOfUnits.h
45 //
48 
49 // Only return a pointer to matrix
51 {
52  return instance;
53 }
54  // This STATIC method delete (!) the old matrix and rewrite a new object returning a pointer to it
55  // TODO A check on the parameters is required!
57 {
58  if (instance) delete instance;
59  instance = new HadrontherapyMatrix(voxelX, voxelY, voxelZ, mass);
60  instance -> Initialize();
61  return instance;
62 }
64  stdFile("Dose.out"),
65  doseUnit(gray)
66 {
67  // Number of the voxels of the phantom
68  // For Y = Z = 1 the phantom is divided in slices (and not in voxels)
69  // orthogonal to the beam axis
70  numberOfVoxelAlongX = voxelX;
71  numberOfVoxelAlongY = voxelY;
72  numberOfVoxelAlongZ = voxelZ;
73  massOfVoxel = mass;
74  // Create the dose matrix
76  if (matrix)
77  {
78  G4cout << "HadrontherapyMatrix: Memory space to store physical dose into " <<
80  " voxels has been allocated " << G4endl;
81  }
82  else G4Exception("HadrontherapyMatrix::HadrontherapyMatrix()", "Hadrontherapy0005", FatalException, "Can't allocate memory to store physical dose!");
83  // Hit voxel (TrackID) marker
84  // This array mark the status of voxel, if a hit occur, with the trackID of the particle
85  // Must be initialized
87  ClearHitTrack();
88 }
89 
92 {
93  delete[] matrix;
94  delete[] hitTrack;
95  // free fluences/dose data memory
96  Clear();
97 }
98 
101 {
102  for (size_t i=0; i<ionStore.size(); i++)
103  {
104  delete[] ionStore[i].dose;
105  delete[] ionStore[i].fluence;
106  }
107  ionStore.clear();
108 }
109 
111 // Initialise the elements of the matrix to zero
113 {
114  // Clear ions store
115  Clear();
116  // Clear dose
118  {
119  matrix[i] = 0;
120  }
121 }
124  // Print generated nuclides list
126 {
127  for (size_t i=0; i<ionStore.size(); i++)
128  {
129  G4cout << ionStore[i].name << G4endl;
130  }
131 }
133  // Clear Hit voxel (TrackID) markers
135 {
137 }
138  // Return Hit status
140 {
141  return &(hitTrack[Index(i,j,k)]);
142 }
144 // Dose methods...
145 // Fill DOSE/fluence matrix for secondary particles:
146 // If fluence parameter is true (default value is FALSE) then fluence at voxel (i, j, k) is increased.
147 // The energyDeposit parameter fill the dose matrix for voxel (i,j,k)
149 
151  G4ParticleDefinition* particleDef,
152  G4int i, G4int j, G4int k,
153  G4double energyDeposit,
154  G4bool fluence)
155 {
156  if ( (energyDeposit <=0. && !fluence) || !secondary) return false;
157  // Get Particle Data Group particle ID
158  G4int PDGencoding = particleDef -> GetPDGEncoding();
159  PDGencoding -= PDGencoding%10;
160 
161  // Search for already allocated data...
162  for (size_t l=0; l < ionStore.size(); l++)
163  {
164  if (ionStore[l].PDGencoding == PDGencoding )
165  { // Is it a primary or a secondary particle?
166  if ( (trackID ==1 && ionStore[l].isPrimary) || (trackID !=1 && !ionStore[l].isPrimary))
167  {
168  if (energyDeposit > 0.) ionStore[l].dose[Index(i, j, k)] += energyDeposit;
169 
170  // Fill a matrix per each ion with the fluence
171  if (fluence) ionStore[l].fluence[Index(i, j, k)]++;
172  return true;
173  }
174  }
175  }
176 
177  G4int Z = particleDef-> GetAtomicNumber();
178  G4int A = particleDef-> GetAtomicMass();
179 
180  G4String fullName = particleDef -> GetParticleName();
181  G4String name = fullName.substr (0, fullName.find("[") ); // cut excitation energy
182  // Let's put a new particle in our store...
183  ion newIon =
184  {
185  (trackID == 1) ? true:false,
186  PDGencoding,
187  name,
188  name.length(),
189  Z,
190  A,
193  };
194  // Initialize data
195  if (newIon.dose && newIon.fluence)
196  {
198  {
199  newIon.dose[q] = 0.;
200  newIon.fluence[q] = 0;
201  }
202  if (energyDeposit > 0.) newIon.dose[Index(i, j, k)] += energyDeposit;
203  if (fluence) newIon.fluence[Index(i, j, k)]++;
204 
205  ionStore.push_back(newIon);
206 
207  // TODO Put some verbosity check
208  /*
209  G4cout << "Memory space to store the DOSE/FLUENCE into " <<
210  numberOfVoxelAlongX*numberOfVoxelAlongY*numberOfVoxelAlongZ <<
211  " voxels has been allocated for the nuclide " << newIon.name <<
212  " (Z = " << Z << ", A = " << A << ")" << G4endl ;
213  */
214  return true;
215  }
216  else // XXX Out of memory! XXX
217  {
218  return false;
219  }
220 
221 }
222 
225  // Methods to store data to filenames...
228  //
229  // General method to store matrix data to filename
230 void HadrontherapyMatrix::StoreMatrix(G4String file, void* data, size_t psize)
231 {
232  if (data)
233  {
234  ofs.open(file, std::ios::out);
235  if (ofs.is_open())
236  {
237  for(G4int i = 0; i < numberOfVoxelAlongX; i++)
238  for(G4int j = 0; j < numberOfVoxelAlongY; j++)
239  for(G4int k = 0; k < numberOfVoxelAlongZ; k++)
240  {
241  G4int n = Index(i, j, k);
242  // Check for data type: u_int, G4double, XXX
243  if (psize == sizeof(unsigned int))
244  {
245  unsigned int* pdata = (unsigned int*)data;
246  if (pdata[n]) ofs << i << '\t' << j << '\t' <<
247  k << '\t' << pdata[n] << G4endl;
248  }
249  else if (psize == sizeof(G4double))
250  {
251  G4double* pdata = (G4double*)data;
252  if (pdata[n]) ofs << i << '\t' << j << '\t' <<
253  k << '\t' << pdata[n] << G4endl;
254  }
255  }
256  ofs.close();
257  }
258  }
259 }
260 
261  // Store fluence per single ion in multiple files
263 {
264  for (size_t i=0; i < ionStore.size(); i++){
265  StoreMatrix(ionStore[i].name + "_Fluence.out", ionStore[i].fluence, sizeof(unsigned int));
266  }
267 }
268  // Store dose per single ion in multiple files
270 {
271 
272  for (size_t i=0; i < ionStore.size(); i++){
273  StoreMatrix(ionStore[i].name + "_Dose.out", ionStore[i].dose, sizeof(G4double));
274  }
275 }
277  // Store dose for all ions into a single file and into ntuples.
278  // Please note that this function is called via messenger commands
279  // defined in the HadrontherapyAnalysisFileMessenger.cc class file
281 {
282 #define width 15L
283  filename = (file=="") ? stdFile:file;
284  // Sort like periodic table
285  std::sort(ionStore.begin(), ionStore.end());
286  G4cout << "Dose is being written to " << filename << G4endl;
287  ofs.open(filename, std::ios::out);
288  if (ofs.is_open())
289  {
290  // Write the voxels index and the list of particles/ions
291  ofs << std::setprecision(6) << std::left <<
292  "i\tj\tk\t";
293  // Total dose
294  ofs << std::setw(width) << "Dose(Gy)";
295  if (secondary)
296  {
297  for (size_t l=0; l < ionStore.size(); l++)
298  {
299  G4String a = (ionStore[l].isPrimary) ? "_1":""; // is it a primary?
300  ofs << std::setw(width) << ionStore[l].name + a <<
301  std::setw(width) << ionStore[l].name + a;
302  }
303  ofs << G4endl;
304 
305  /*
306  * PDGencondig
307  */
308  /*
309  ofs << std::setprecision(6) << std::left <<
310  "0\t0\t0\t";
311 
312  // Total dose
313  ofs << std::setw(width) << '0';
314  for (size_t l=0; l < ionStore.size(); l++)
315  {
316  ofs << std::setw(width) << ionStore[l].PDGencoding <<
317  std::setw(width) << ionStore[l].PDGencoding;
318  }
319  ofs << G4endl;
320  */
321  }
322  // Write data
323  for(G4int i = 0; i < numberOfVoxelAlongX; i++)
324  for(G4int j = 0; j < numberOfVoxelAlongY; j++)
325  for(G4int k = 0; k < numberOfVoxelAlongZ; k++)
326  {
327  G4int n = Index(i, j, k);
328  // Write only not identically null data lines
329  if (matrix[n])
330  {
331  ofs << G4endl;
332  ofs << i << '\t' << j << '\t' << k << '\t';
333  // Total dose
334  ofs << std::setw(width) << (matrix[n]/massOfVoxel)/doseUnit;
335  if (secondary)
336  {
337  for (size_t l=0; l < ionStore.size(); l++)
338  {
339  // Fill ASCII file rows
340  ofs << std::setw(width) << ionStore[l].dose[n]/massOfVoxel/doseUnit <<
341  std::setw(width) << ionStore[l].fluence[n];
342  }
343  }
344  }
345  }
346  ofs.close();
347  }
348 }
350 
351 #ifdef G4ANALYSIS_USE_ROOT
352 void HadrontherapyMatrix::StoreDoseFluenceRoot()
353 {
355  if (analysis -> IsTheTFile())
356  {
357  for(G4int i = 0; i < numberOfVoxelAlongX; i++)
358  for(G4int j = 0; j < numberOfVoxelAlongY; j++)
359  for(G4int k = 0; k < numberOfVoxelAlongZ; k++)
360  {
361  G4int n = Index(i, j, k);
362  for (size_t l=0; l < ionStore.size(); l++)
363 
364  {
365  // Do the same work for .root file: fill dose/fluence ntuple
366  analysis -> FillVoxelFragmentTuple( i, j, k,
367  ionStore[l].A,
368  ionStore[l].Z,
369  ionStore[l].dose[n]/massOfVoxel/doseUnit,
370  ionStore[l].fluence[n] );
371 
372 
373  }
374  }
375  }
376 }
377 #endif
378 
380  G4double energyDeposit)
381 {
382  if (matrix)
383  matrix[Index(i,j,k)] += energyDeposit;
384 
385  // Store the energy deposit in the matrix element corresponding
386  // to the phantom voxel
387 }
389 {
390  // Convert energy deposited to dose.
391  // Store the information of the matrix in a ntuple and in
392  // a 1D Histogram
393 #ifdef G4ANALYSIS_USE_ROOT
395 #endif
396 
397  if (matrix)
398  {
399  for(G4int i = 0; i < numberOfVoxelAlongX; i++)
400  for(G4int j = 0; j < numberOfVoxelAlongY; j++)
401  for(G4int k = 0; k < numberOfVoxelAlongZ; k++)
402  {
403 #ifdef G4ANALYSIS_USE_ROOT
404  G4int n = Index(i,j,k);
405  if (analysis -> IsTheTFile() )
406  {
407  analysis -> FillEnergyDeposit(i, j, k, matrix[n]/massOfVoxel/doseUnit);
408  analysis -> BraggPeak(i, matrix[n]/massOfVoxel/doseUnit);
409  }
410 #endif
411  }
412  }
413 }
414 
static HadrontherapyAnalysisManager * GetInstance()
Get the pointer to the analysis manager.
G4double * dose
G4int Index(G4int i, G4int j, G4int k)
G4String name
Definition: TRTMaterials.hh:40
#define width
void StoreDoseFluenceAscii(G4String filename="")
G4double a
Definition: TRTMaterials.hh:39
int G4int
Definition: G4Types.hh:78
static HadrontherapyMatrix * GetInstance()
void StoreMatrix(G4String file, void *data, size_t psize)
G4GLOB_DLL std::ostream G4cout
unsigned int * fluence
bool G4bool
Definition: G4Types.hh:79
G4int * GetHitTrack(G4int i, G4int j, G4int k)
G4bool Fill(G4int, G4ParticleDefinition *particleDef, G4int i, G4int j, G4int k, G4double energyDeposit, G4bool fluence=false)
const G4int n
static const G4double A[nN]
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
static const double gray
Definition: G4SIunits.hh:276
HadrontherapyMatrix(G4int numberOfVoxelAlongX, G4int numberOfVoxelAlongY, G4int numberOfVoxelAlongZ, G4double massOfVoxel)
A class for connecting the simulation to an analysis package.
static HadrontherapyMatrix * instance
#define G4endl
Definition: G4ios.hh:61
double G4double
Definition: G4Types.hh:76
std::vector< ion > ionStore