Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DicomDetectorConstruction.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 //
28 
29 #include "globals.hh"
30 
31 #include "G4Box.hh"
32 #include "G4LogicalVolume.hh"
33 #include "G4VPhysicalVolume.hh"
34 #include "G4PVPlacement.hh"
35 #include "G4Material.hh"
36 #include "G4Element.hh"
37 #include "G4UIcommand.hh"
38 #include "G4PhysicalConstants.hh"
39 #include "G4SystemOfUnits.hh"
40 
43 
44 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
46 {
47  fAir = 0;
48 
49  fWorld_solid = 0;
50  fWorld_logic = 0;
51  fWorld_phys = 0;
52 
53  fContainer_solid = 0;
54  fContainer_logic = 0;
55  fContainer_phys = 0;
56 
57  fNoFiles = 0;
58  fMateIDs = 0;
59 
61 
62  fNVoxelX = 0;
63  fNVoxelY = 0;
64  fNVoxelZ = 0;
65  fVoxelHalfDimX = 0;
66  fVoxelHalfDimY = 0;
67  fVoxelHalfDimZ = 0;
68 
69 }
70 
71 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
73 {
74 }
75 
76 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
78 {
80 
81  //----- Build world
82  G4double worldXDimension = 1.*m;
83  G4double worldYDimension = 1.*m;
84  G4double worldZDimension = 1.*m;
85 
86  fWorld_solid = new G4Box( "WorldSolid",
87  worldXDimension,
88  worldYDimension,
89  worldZDimension );
90 
92  fAir,
93  "WorldLogical",
94  0, 0, 0 );
95 
96  fWorld_phys = new G4PVPlacement( 0,
97  G4ThreeVector(0,0,0),
98  "World",
100  0,
101  false,
102  0 );
103 
104  ReadPhantomData();
105 
108 
109  return fWorld_phys;
110 }
111 
112 
113 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
115 {
116  // Creating elements :
117  G4double z, a, density;
119 
120  G4Element* elC = new G4Element( name = "Carbon",
121  symbol = "C",
122  z = 6.0, a = 12.011 * g/mole );
123  G4Element* elH = new G4Element( name = "Hydrogen",
124  symbol = "H",
125  z = 1.0, a = 1.008 * g/mole );
126  G4Element* elN = new G4Element( name = "Nitrogen",
127  symbol = "N",
128  z = 7.0, a = 14.007 * g/mole );
129  G4Element* elO = new G4Element( name = "Oxygen",
130  symbol = "O",
131  z = 8.0, a = 16.00 * g/mole );
132  G4Element* elNa = new G4Element( name = "Sodium",
133  symbol = "Na",
134  z= 11.0, a = 22.98977* g/mole );
135  G4Element* elS = new G4Element( name = "Sulfur",
136  symbol = "S",
137  z = 16.0,a = 32.065* g/mole );
138  G4Element* elCl = new G4Element( name = "Chlorine",
139  symbol = "P",
140  z = 17.0, a = 35.453* g/mole );
141  G4Element* elK = new G4Element( name = "Potassium",
142  symbol = "P",
143  z = 19.0, a = 30.0983* g/mole );
144  G4Element* elP = new G4Element( name = "Phosphorus",
145  symbol = "P",
146  z = 30.0, a = 30.973976* g/mole );
147  G4Element* elFe = new G4Element( name = "Iron",
148  symbol = "Fe",
149  z = 26, a = 56.845* g/mole );
150  G4Element* elMg = new G4Element( name = "Magnesium",
151  symbol = "Mg",
152  z = 12.0, a = 24.3050* g/mole );
153  G4Element* elCa = new G4Element( name="Calcium",
154  symbol = "Ca",
155  z = 20.0, a = 40.078* g/mole );
156 
157  // Creating Materials :
158  G4int numberofElements;
159 
160  // Air
161  fAir = new G4Material( "Air",
162  1.290*mg/cm3,
163  numberofElements = 2 );
164  fAir->AddElement(elN, 0.7);
165  fAir->AddElement(elO, 0.3);
166 
167  // Lung Inhale
168  G4Material* lunginhale = new G4Material( "LungInhale",
169  density = 0.217*g/cm3,
170  numberofElements = 9);
171  lunginhale->AddElement(elH,0.103);
172  lunginhale->AddElement(elC,0.105);
173  lunginhale->AddElement(elN,0.031);
174  lunginhale->AddElement(elO,0.749);
175  lunginhale->AddElement(elNa,0.002);
176  lunginhale->AddElement(elP,0.002);
177  lunginhale->AddElement(elS,0.003);
178  lunginhale->AddElement(elCl,0.002);
179  lunginhale->AddElement(elK,0.003);
180 
181  // Lung exhale
182  G4Material* lungexhale = new G4Material( "LungExhale",
183  density = 0.508*g/cm3,
184  numberofElements = 9 );
185  lungexhale->AddElement(elH,0.103);
186  lungexhale->AddElement(elC,0.105);
187  lungexhale->AddElement(elN,0.031);
188  lungexhale->AddElement(elO,0.749);
189  lungexhale->AddElement(elNa,0.002);
190  lungexhale->AddElement(elP,0.002);
191  lungexhale->AddElement(elS,0.003);
192  lungexhale->AddElement(elCl,0.002);
193  lungexhale->AddElement(elK,0.003);
194 
195  // Adipose tissue
196  G4Material* adiposeTissue = new G4Material( "AdiposeTissue",
197  density = 0.967*g/cm3,
198  numberofElements = 7);
199  adiposeTissue->AddElement(elH,0.114);
200  adiposeTissue->AddElement(elC,0.598);
201  adiposeTissue->AddElement(elN,0.007);
202  adiposeTissue->AddElement(elO,0.278);
203  adiposeTissue->AddElement(elNa,0.001);
204  adiposeTissue->AddElement(elS,0.001);
205  adiposeTissue->AddElement(elCl,0.001);
206 
207  // Breast
208  G4Material* breast = new G4Material( "Breast",
209  density = 0.990*g/cm3,
210  numberofElements = 8 );
211  breast->AddElement(elH,0.109);
212  breast->AddElement(elC,0.506);
213  breast->AddElement(elN,0.023);
214  breast->AddElement(elO,0.358);
215  breast->AddElement(elNa,0.001);
216  breast->AddElement(elP,0.001);
217  breast->AddElement(elS,0.001);
218  breast->AddElement(elCl,0.001);
219 
220  // Water
221  G4Material* water = new G4Material( "Water",
222  density = 1.0*g/cm3,
223  numberofElements = 2 );
224  water->AddElement(elH,0.112);
225  water->AddElement(elO,0.888);
226 
227  // Muscle
228  G4Material* muscle = new G4Material( "Muscle",
229  density = 1.061*g/cm3,
230  numberofElements = 9 );
231  muscle->AddElement(elH,0.102);
232  muscle->AddElement(elC,0.143);
233  muscle->AddElement(elN,0.034);
234  muscle->AddElement(elO,0.710);
235  muscle->AddElement(elNa,0.001);
236  muscle->AddElement(elP,0.002);
237  muscle->AddElement(elS,0.003);
238  muscle->AddElement(elCl,0.001);
239  muscle->AddElement(elK,0.004);
240 
241  // Liver
242  G4Material* liver = new G4Material( "Liver",
243  density = 1.071*g/cm3,
244  numberofElements = 9);
245  liver->AddElement(elH,0.102);
246  liver->AddElement(elC,0.139);
247  liver->AddElement(elN,0.030);
248  liver->AddElement(elO,0.716);
249  liver->AddElement(elNa,0.002);
250  liver->AddElement(elP,0.003);
251  liver->AddElement(elS,0.003);
252  liver->AddElement(elCl,0.002);
253  liver->AddElement(elK,0.003);
254 
255  // Trabecular Bone
256  G4Material* trabecularBone = new G4Material( "TrabecularBone",
257  density = 1.159*g/cm3,
258  numberofElements = 12 );
259  trabecularBone->AddElement(elH,0.085);
260  trabecularBone->AddElement(elC,0.404);
261  trabecularBone->AddElement(elN,0.058);
262  trabecularBone->AddElement(elO,0.367);
263  trabecularBone->AddElement(elNa,0.001);
264  trabecularBone->AddElement(elMg,0.001);
265  trabecularBone->AddElement(elP,0.034);
266  trabecularBone->AddElement(elS,0.002);
267  trabecularBone->AddElement(elCl,0.002);
268  trabecularBone->AddElement(elK,0.001);
269  trabecularBone->AddElement(elCa,0.044);
270  trabecularBone->AddElement(elFe,0.001);
271 
272  // Dense Bone
273  G4Material* denseBone = new G4Material( "DenseBone",
274  density = 1.575*g/cm3,
275  numberofElements = 11 );
276  denseBone->AddElement(elH,0.056);
277  denseBone->AddElement(elC,0.235);
278  denseBone->AddElement(elN,0.050);
279  denseBone->AddElement(elO,0.434);
280  denseBone->AddElement(elNa,0.001);
281  denseBone->AddElement(elMg,0.001);
282  denseBone->AddElement(elP,0.072);
283  denseBone->AddElement(elS,0.003);
284  denseBone->AddElement(elCl,0.001);
285  denseBone->AddElement(elK,0.001);
286  denseBone->AddElement(elCa,0.146);
287 
288  //----- Put the materials in a vector
289  fOriginalMaterials.push_back(fAir); // rho = 0.00129
290  fOriginalMaterials.push_back(lunginhale); // rho = 0.217
291  fOriginalMaterials.push_back(lungexhale); // rho = 0.508
292  fOriginalMaterials.push_back(adiposeTissue); // rho = 0.967
293  fOriginalMaterials.push_back(breast ); // rho = 0.990
294  fOriginalMaterials.push_back(water); // rho = 1.018
295  fOriginalMaterials.push_back(muscle); // rho = 1.061
296  fOriginalMaterials.push_back(liver); // rho = 1.071
297  fOriginalMaterials.push_back(trabecularBone); // rho = 1.159
298  fOriginalMaterials.push_back(denseBone); // rho = 1.575
299 
300 }
301 
302 
303 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
305 {
306  std::ifstream finDF("Data.dat");
307  G4String fname;
308  if(finDF.good() != 1 ) {
309  G4Exception(" DicomDetectorConstruction::ReadPhantomData",
310  "",
312  "Problem reading data file: Data.dat");
313  }
314 
315  G4int compression;
316  finDF >> compression; // not used here
317 
318  finDF >> fNoFiles;
319  for(G4int i = 0; i < fNoFiles; i++ ) {
320  finDF >> fname;
321  //--- Read one data file
322  fname += ".g4dcm";
323  ReadPhantomDataFile(fname);
324  }
325 
326  //----- Merge data headers
328 
329  finDF.close();
330 
331 }
332 
333 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
335 {
336 #ifdef G4VERBOSE
337  G4cout << " DicomDetectorConstruction::ReadPhantomDataFile opening file " << fname << G4endl;
338 #endif
339  std::ifstream fin(fname.c_str(), std::ios_base::in);
340  if( !fin.is_open() ) {
341  G4Exception("DicomDetectorConstruction::ReadPhantomDataFile",
342  "",
344  G4String("File not found " + fname ).c_str());
345  }
346  //----- Define density differences (maximum density difference to create a new material)
347  char* part = getenv( "DICOM_CHANGE_MATERIAL_DENSITY" );
348  G4double densityDiff = -1.;
349  if( part ) densityDiff = G4UIcommand::ConvertToDouble(part);
350  if( densityDiff != -1. ) {
351  for( unsigned int ii = 0; ii < fOriginalMaterials.size(); ii++ ){
352  fDensityDiffs[ii] = densityDiff; //currently all materials with same difference
353  }
354  }else {
355  if( fMaterials.size() == 0 ) { // do it only for first slice
356  for( unsigned int ii = 0; ii < fOriginalMaterials.size(); ii++ ){
357  fMaterials.push_back( fOriginalMaterials[ii] );
358  }
359  }
360  }
361 
362  //----- Read data header
364  fZSliceHeaders.push_back( sliceHeader );
365 
366  //----- Read material indices
367  G4int nVoxels = sliceHeader->GetNoVoxels();
368 
369  //--- If first slice, initiliaze fMateIDs
370  if( fZSliceHeaders.size() == 1 ) {
371  //fMateIDs = new unsigned int[fNoFiles*nVoxels];
372  fMateIDs = new size_t[fNoFiles*nVoxels];
373 
374  }
375 
376  unsigned int mateID;
377  G4int voxelCopyNo = (fZSliceHeaders.size()-1)*nVoxels; // number of voxels from previously read slices
378  for( G4int ii = 0; ii < nVoxels; ii++, voxelCopyNo++ ){
379  fin >> mateID;
380  fMateIDs[voxelCopyNo] = mateID;
381  }
382 
383  //----- Read material densities and build new materials if two voxels have same material but its density is in a different density interval (size of density intervals defined by densityDiff)
385  voxelCopyNo = (fZSliceHeaders.size()-1)*nVoxels; // number of voxels from previously read slices
386  for( G4int ii = 0; ii < nVoxels; ii++, voxelCopyNo++ ){
387  fin >> density;
388 
389  //-- Get material from list of original materials
390  mateID = fMateIDs[voxelCopyNo];
391  G4Material* mateOrig = fOriginalMaterials[mateID];
392 
393  //-- Get density bin: middle point of the bin in which the current density is included
394  G4String newMateName = mateOrig->GetName();
395  float densityBin = 0.;
396  if( densityDiff != -1.) {
397  densityBin = fDensityDiffs[mateID] * (G4int(density/fDensityDiffs[mateID])+0.5);
398  //-- Build the new material name
399  newMateName += G4UIcommand::ConvertToString(densityBin);
400  }
401 
402  //-- Look if a material with this name is already created (because a previous voxel was already in this density bin)
403  unsigned int im;
404  for( im = 0; im < fMaterials.size(); im++ ){
405  if( fMaterials[im]->GetName() == newMateName ) {
406  break;
407  }
408  }
409  //-- If material is already created use index of this material
410  if( im != fMaterials.size() ) {
411  fMateIDs[voxelCopyNo] = im;
412  //-- else, create the material
413  } else {
414  if( densityDiff != -1.) {
415  fMaterials.push_back( BuildMaterialWithChangingDensity( mateOrig, densityBin, newMateName ) );
416  fMateIDs[voxelCopyNo] = fMaterials.size()-1;
417  } else {
418  G4cerr << " im " << im << " < " << fMaterials.size() << " name " << newMateName << G4endl;
419  G4Exception("DicomDetectorConstruction::ReadPhantomDataFile",
420  "",
422  "Wrong index in material"); //it should never reach here
423  }
424  }
425  }
426 
427 }
428 
429 
430 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
432 {
433  //----- Images must have the same dimension ...
435  for( unsigned int ii = 1; ii < fZSliceHeaders.size(); ii++ ) {
437  };
438 }
439 
440 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
442 {
443  //----- Copy original material, but with new density
444  G4int nelem = origMate->GetNumberOfElements();
445  G4Material* mate = new G4Material( newMateName, density*g/cm3, nelem, kStateUndefined, STP_Temperature );
446 
447  for( G4int ii = 0; ii < nelem; ii++ ){
448  G4double frac = origMate->GetFractionVector()[ii];
449  G4Element* elem = const_cast<G4Element*>(origMate->GetElement(ii));
450  mate->AddElement( elem, frac );
451  }
452 
453  return mate;
454 }
455 
456 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
458 {
459  //---- Extract number of voxels and voxel dimensions
463 
467 #ifdef G4VERBOSE
468  G4cout << " fNVoxelX " << fNVoxelX << " fVoxelHalfDimX " << fVoxelHalfDimX <<G4endl;
469  G4cout << " fNVoxelY " << fNVoxelY << " fVoxelHalfDimY " << fVoxelHalfDimY <<G4endl;
470  G4cout << " fNVoxelZ " << fNVoxelZ << " fVoxelHalfDimZ " << fVoxelHalfDimZ <<G4endl;
471  G4cout << " totalPixels " << fNVoxelX*fNVoxelY*fNVoxelZ << G4endl;
472 #endif
473 
474  //----- Define the volume that contains all the voxels
478  fMaterials[0], //the material is not important, it will be fully filled by the voxels
479  "phantomContainer",
480  0, 0, 0 );
481  //--- Place it on the world
485  G4ThreeVector posCentreVoxels(fOffsetX,fOffsetY,fOffsetZ);
486 #ifdef G4VERBOSE
487  G4cout << " placing voxel container volume at " << posCentreVoxels << G4endl;
488 #endif
489  fContainer_phys =
490  new G4PVPlacement(0, // rotation
491  posCentreVoxels,
492  fContainer_logic, // The logic volume
493  "phantomContainer", // Name
494  fWorld_logic, // Mother
495  false, // No op. bool.
496  1); // Copy number
497 
498 }
499 
500 
501 #include "G4SDManager.hh"
503 #include "G4PSDoseDeposit.hh"
504 
505 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
507 {
508 
510  //
511  // Sensitive Detector Name
512  G4String concreteSDname = "phantomSD";
513 
514  //------------------------
515  // MultiFunctionalDetector
516  //------------------------
517  //
518  // Define MultiFunctionalDetector with name.
519  G4MultiFunctionalDetector* MFDet = new G4MultiFunctionalDetector(concreteSDname);
520  SDman->AddNewDetector( MFDet ); // Register SD to SDManager
521 
522  voxel_logic->SetSensitiveDetector(MFDet);
523 
524  G4PSDoseDeposit* scorer = new G4PSDoseDeposit("DoseDeposit");
525  MFDet->RegisterPrimitive(scorer);
526 
527 }
528