Geant4  10.03.p03
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HadrontherapyDetectorConstruction.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 //
26 // Hadrontherapy advanced example for Geant4
27 // See more at: https://twiki.cern.ch/twiki/bin/view/Geant4/AdvancedExamplesHadrontherapy
28 
29 #include "G4UnitsTable.hh"
30 #include "G4SDManager.hh"
31 #include "G4RunManager.hh"
32 #include "G4GeometryManager.hh"
33 #include "G4SolidStore.hh"
34 #include "G4PhysicalVolumeStore.hh"
35 #include "G4LogicalVolumeStore.hh"
36 #include "G4Box.hh"
37 #include "G4LogicalVolume.hh"
38 #include "G4ThreeVector.hh"
39 #include "G4PVPlacement.hh"
40 #include "globals.hh"
41 #include "G4Transform3D.hh"
42 #include "G4RotationMatrix.hh"
43 #include "G4Colour.hh"
44 #include "G4UserLimits.hh"
45 #include "G4UnitsTable.hh"
46 #include "G4VisAttributes.hh"
47 #include "G4NistManager.hh"
52 #include "HadrontherapyMatrix.hh"
53 #include "HadrontherapyLet.hh"
54 #include "PassiveProtonBeamLine.hh"
56 #include "G4SystemOfUnits.hh"
57 
58 #include <cmath>
59 
60 HadrontherapyDetectorConstruction* HadrontherapyDetectorConstruction::instance = 0;
63 : motherPhys(physicalTreatmentRoom), // pointer to WORLD volume
64 detectorSD(0), detectorROGeometry(0), matrix(0),
65 phantom(0), detector(0),
66 phantomLogicalVolume(0), detectorLogicalVolume(0),
67 phantomPhysicalVolume(0), detectorPhysicalVolume(0),
68 aRegion(0)
69 {
71 
72  /* NOTE! that the HadrontherapyDetectorConstruction class
73  * does NOT inherit from G4VUserDetectorConstruction G4 class
74  * So the Construct() mandatory virtual method is inside another geometric class
75  * like the passiveProtonBeamLIne, ...
76  */
77 
78  // Messenger to change parameters of the phantom/detector geometry
79  detectorMessenger = new HadrontherapyDetectorMessenger(this);
80 
81  // Default detector voxels size
82  // 200 slabs along the beam direction (X)
83  sizeOfVoxelAlongX = 200 *um;
84  sizeOfVoxelAlongY = 4 *cm;
85  sizeOfVoxelAlongZ = 4 *cm;
86 
87  // Define here the material of the water phantom and of the detector
88  SetPhantomMaterial("G4_WATER");
89  // Construct geometry (messenger commands)
90  SetDetectorSize(4.*cm, 4.*cm, 4.*cm);
91  SetPhantomSize(40. *cm, 40. *cm, 40. *cm);
92  SetPhantomPosition(G4ThreeVector(20. *cm, 0. *cm, 0. *cm));
95  //GetDetectorToWorldPosition();
96 
97  // Write virtual parameters to the real ones and check for consistency
99 }
100 
103 {
104  delete detectorROGeometry;
105  delete matrix;
106  delete detectorMessenger;
107 }
108 
111 {
112  return instance;
113 }
114 
116 // ConstructPhantom() is the method that construct a water box (called phantom
117 // (or water phantom) in the usual Medical physicists slang).
118 // A water phantom can be considered a good approximation of a an human body.
119 void HadrontherapyDetectorConstruction::ConstructPhantom()
120 {
121  // Definition of the solid volume of the Phantom
122  phantom = new G4Box("Phantom",
123  phantomSizeX/2,
124  phantomSizeY/2,
125  phantomSizeZ/2);
126 
127  // Definition of the logical volume of the Phantom
128  phantomLogicalVolume = new G4LogicalVolume(phantom,
129  phantomMaterial,
130  "phantomLog", 0, 0, 0);
131 
132  // Definition of the physics volume of the Phantom
133  phantomPhysicalVolume = new G4PVPlacement(0,
134  phantomPosition,
135  "phantomPhys",
136  phantomLogicalVolume,
137  motherPhys,
138  false,
139  0);
140 
141  // Visualisation attributes of the phantom
142  red = new G4VisAttributes(G4Colour(255/255., 0/255. ,0/255.));
143  red -> SetVisibility(true);
144  red -> SetForceSolid(true);
145  red -> SetForceWireframe(true);
146  phantomLogicalVolume -> SetVisAttributes(red);
147 }
148 
150 // ConstructDetector() is the method the reconstruct a detector region
151 // inside the water phantom. It is a volume, located inside the water phantom.
152 //
153 // **************************
154 // * water phantom *
155 // * *
156 // * *
157 // *--------------- *
158 // Beam * - *
159 // -----> * detector - *
160 // * - *
161 // *--------------- *
162 // * *
163 // * *
164 // * *
165 // **************************
166 //
167 // The detector can be dived in slices or voxelized
168 // and inside it different quantities (dose distribution, fluence distribution, LET, etc)
169 // can be stored.
170 void HadrontherapyDetectorConstruction::ConstructDetector()
171 {
172  // Definition of the solid volume of the Detector
173  detector = new G4Box("Detector",
174  detectorSizeX/2,
175  detectorSizeY/2,
176  detectorSizeZ/2);
177 
178  // Definition of the logic volume of the Phantom
179  detectorLogicalVolume = new G4LogicalVolume(detector,
180  detectorMaterial,
181  "DetectorLog",
182  0,0,0);
183  // Definition of the physical volume of the Phantom
184  detectorPhysicalVolume = new G4PVPlacement(0,
185  detectorPosition, // Setted by displacement
186  "DetectorPhys",
187  detectorLogicalVolume,
188  phantomPhysicalVolume,
189  false,0);
190 
191  // Visualisation attributes of the detector
192  skyBlue = new G4VisAttributes( G4Colour(135/255. , 206/255. , 235/255. ));
193  skyBlue -> SetVisibility(true);
194  skyBlue -> SetForceSolid(true);
195  //skyBlue -> SetForceWireframe(true);
196  detectorLogicalVolume -> SetVisAttributes(skyBlue);
197 
198  // **************
199  // Cut per Region
200  // **************
201  //
202  // A smaller cut is fixed in the phantom to calculate the energy deposit with the
203  // required accuracy
204  if (!aRegion)
205  {
206  aRegion = new G4Region("DetectorLog");
207  detectorLogicalVolume -> SetRegion(aRegion);
208  aRegion -> AddRootLogicalVolume(detectorLogicalVolume);
209  }
210 }
211 
216  detectorToWorldPosition)
217 {
218  RO->Initialize(detectorToWorldPosition,
219  detectorSizeX/2,
220  detectorSizeY/2,
221  detectorSizeZ/2,
222  numberOfVoxelsAlongX,
223  numberOfVoxelsAlongY,
224  numberOfVoxelsAlongZ);
225 }
226 
228 void HadrontherapyDetectorConstruction::ParametersCheck()
229 {
230  // Check phantom/detector sizes & relative position
231  if (!IsInside(detectorSizeX,
232  detectorSizeY,
233  detectorSizeZ,
234  phantomSizeX,
235  phantomSizeY,
236  phantomSizeZ,
237  detectorToPhantomPosition
238  ))
239  G4Exception("HadrontherapyDetectorConstruction::ParametersCheck()", "Hadrontherapy0001", FatalException, "Error: Detector is not fully inside Phantom!");
240 
241  // Check Detector sizes respect to the voxel ones
242 
243  if ( detectorSizeX < sizeOfVoxelAlongX) {
244  G4Exception("HadrontherapyDetectorConstruction::ParametersCheck()", "Hadrontherapy0002", FatalException, "Error: Detector X size must be bigger or equal than that of Voxel X!");
245  }
246  if ( detectorSizeY < sizeOfVoxelAlongY) {
247  G4Exception(" HadrontherapyDetectorConstruction::ParametersCheck()", "Hadrontherapy0003", FatalException, "Error: Detector Y size must be bigger or equal than that of Voxel Y!");
248  }
249  if ( detectorSizeZ < sizeOfVoxelAlongZ) {
250  G4Exception(" HadrontherapyDetectorConstruction::ParametersCheck()", "Hadrontherapy0004", FatalException, "Error: Detector Z size must be bigger or equal than that of Voxel Z!");
251  }
252 }
253 
256 {
257 
258  if (G4Material* pMat = G4NistManager::Instance()->FindOrBuildMaterial(material, false) )
259  {
260  phantomMaterial = pMat;
261  detectorMaterial = pMat;
262  if (detectorLogicalVolume && phantomLogicalVolume)
263  {
264  detectorLogicalVolume -> SetMaterial(pMat);
265  phantomLogicalVolume -> SetMaterial(pMat);
266 
267  G4RunManager::GetRunManager() -> PhysicsHasBeenModified();
269  G4cout << "The material of Phantom/Detector has been changed to " << material << G4endl;
270  }
271  }
272  else
273  {
274  G4cout << "WARNING: material \"" << material << "\" doesn't exist in NIST elements/materials"
275  " table [located in $G4INSTALL/source/materials/src/G4NistMaterialBuilder.cc]" << G4endl;
276  G4cout << "Use command \"/parameter/nist\" to see full materials list!" << G4endl;
277  return false;
278  }
279 
280  return true;
281 }
284 {
285  if (sizeX > 0.) phantomSizeX = sizeX;
286  if (sizeY > 0.) phantomSizeY = sizeY;
287  if (sizeZ > 0.) phantomSizeZ = sizeZ;
288 }
289 
292 {
293  if (sizeX > 0.) {detectorSizeX = sizeX;}
294  if (sizeY > 0.) {detectorSizeY = sizeY;}
295  if (sizeZ > 0.) {detectorSizeZ = sizeZ;}
296  SetVoxelSize(sizeOfVoxelAlongX, sizeOfVoxelAlongY, sizeOfVoxelAlongZ);
297 }
298 
301 {
302  if (sizeX > 0.) {sizeOfVoxelAlongX = sizeX;}
303  if (sizeY > 0.) {sizeOfVoxelAlongY = sizeY;}
304  if (sizeZ > 0.) {sizeOfVoxelAlongZ = sizeZ;}
305 }
306 
309 {
310  phantomPosition = pos;
311 }
312 
315 {
316  detectorToPhantomPosition = displ;
317 }
318 
321 {
322  /*
323  * Check parameters consistency
324  */
325  ParametersCheck();
326 
327  G4GeometryManager::GetInstance() -> OpenGeometry();
328  if (phantom)
329  {
330  phantom -> SetXHalfLength(phantomSizeX/2);
331  phantom -> SetYHalfLength(phantomSizeY/2);
332  phantom -> SetZHalfLength(phantomSizeZ/2);
333  phantomPhysicalVolume -> SetTranslation(phantomPosition);
334  }
335  else ConstructPhantom();
336 
337  // Get the center of the detector
339  if (detector)
340  {
341  detector -> SetXHalfLength(detectorSizeX/2);
342  detector -> SetYHalfLength(detectorSizeY/2);
343  detector -> SetZHalfLength(detectorSizeZ/2);
344  detectorPhysicalVolume -> SetTranslation(detectorPosition);
345  }
346  else ConstructDetector();
347 
348  // Round to nearest integer number of voxel
349 
350  numberOfVoxelsAlongX = G4lrint(detectorSizeX / sizeOfVoxelAlongX);
351  sizeOfVoxelAlongX = ( detectorSizeX / numberOfVoxelsAlongX );
352  numberOfVoxelsAlongY = G4lrint(detectorSizeY / sizeOfVoxelAlongY);
353  sizeOfVoxelAlongY = ( detectorSizeY / numberOfVoxelsAlongY );
354  numberOfVoxelsAlongZ = G4lrint(detectorSizeZ / sizeOfVoxelAlongZ);
355  sizeOfVoxelAlongZ = ( detectorSizeZ / numberOfVoxelsAlongZ );
357 
359 
361 
362  //Set parameters, either for the Construct() or for the UpdateROGeometry()
364  detectorSizeX/2,
365  detectorSizeY/2,
366  detectorSizeZ/2,
367  numberOfVoxelsAlongX,
368  numberOfVoxelsAlongY,
369  numberOfVoxelsAlongZ);
370 
371  //This method below has an effect only if the RO geometry is already built.
372  RO->UpdateROGeometry();
373 
374 
375 
376  volumeOfVoxel = sizeOfVoxelAlongX * sizeOfVoxelAlongY * sizeOfVoxelAlongZ;
377  massOfVoxel = detectorMaterial -> GetDensity() * volumeOfVoxel;
378  // This will clear the existing matrix (together with all data inside it)!
379  matrix = HadrontherapyMatrix::GetInstance(numberOfVoxelsAlongX,
380  numberOfVoxelsAlongY,
381  numberOfVoxelsAlongZ,
382  massOfVoxel);
383 
384 
385  // Comment out the line below if let calculation is not needed!
386  // Initialize LET with energy of primaries and clear data inside
387  if ( (let = HadrontherapyLet::GetInstance(this)) )
388  {
390  }
391 
392 
393  // Initialize analysis
394 #ifdef G4ANALYSIS_USE_ROOT
396  analysis -> flush(); // Finalize the root file
397  analysis -> book();
398 #endif
399  // Inform the kernel about the new geometry
401  G4RunManager::GetRunManager() -> PhysicsHasBeenModified();
402 
403  PrintParameters();
404  // CheckOverlaps();
405 }
406 
408 //Check of the geometry
410 void HadrontherapyDetectorConstruction::CheckOverlaps()
411 {
413  G4cout << thePVStore->size() << " physical volumes are defined" << G4endl;
414  G4bool overlapFlag = false;
415  G4int res=1000;
416  G4double tol=0.; //tolerance
417  for (size_t i=0;i<thePVStore->size();i++)
418  {
419  //overlapFlag = (*thePVStore)[i]->CheckOverlaps(res,tol,fCheckOverlapsVerbosity) | overlapFlag;
420  overlapFlag = (*thePVStore)[i]->CheckOverlaps(res,tol,true) | overlapFlag; }
421  if (overlapFlag)
422  G4cout << "Check: there are overlapping volumes" << G4endl;
423 }
424 
427 {
428 
429  G4cout << "The (X,Y,Z) dimensions of the phantom are : (" <<
430  G4BestUnit( phantom -> GetXHalfLength()*2., "Length") << ',' <<
431  G4BestUnit( phantom -> GetYHalfLength()*2., "Length") << ',' <<
432  G4BestUnit( phantom -> GetZHalfLength()*2., "Length") << ')' << G4endl;
433 
434  G4cout << "The (X,Y,Z) dimensions of the detector are : (" <<
435  G4BestUnit( detector -> GetXHalfLength()*2., "Length") << ',' <<
436  G4BestUnit( detector -> GetYHalfLength()*2., "Length") << ',' <<
437  G4BestUnit( detector -> GetZHalfLength()*2., "Length") << ')' << G4endl;
438 
439  G4cout << "Displacement between Phantom and World is: ";
440  G4cout << "DX= "<< G4BestUnit(phantomPosition.getX(),"Length") <<
441  "DY= "<< G4BestUnit(phantomPosition.getY(),"Length") <<
442  "DZ= "<< G4BestUnit(phantomPosition.getZ(),"Length") << G4endl;
443 
444  G4cout << "The (X,Y,Z) sizes of the Voxels are: (" <<
445  G4BestUnit(sizeOfVoxelAlongX, "Length") << ',' <<
446  G4BestUnit(sizeOfVoxelAlongY, "Length") << ',' <<
447  G4BestUnit(sizeOfVoxelAlongZ, "Length") << ')' << G4endl;
448 
449  G4cout << "The number of Voxels along (X,Y,Z) is: (" <<
450  numberOfVoxelsAlongX << ',' <<
451  numberOfVoxelsAlongY <<',' <<
452  numberOfVoxelsAlongZ << ')' << G4endl;
453 }
454 
static HadrontherapyAnalysisManager * GetInstance()
void SetPhantomSize(G4double sizeX, G4double sizeY, G4double sizeZ)
CLHEP::Hep3Vector G4ThreeVector
Definition: G4Box.hh:64
static HadrontherapyLet * GetInstance()
const G4VUserDetectorConstruction * GetUserDetectorConstruction() const
void Initialize()
Definition: errprop.cc:101
void Initialize(G4ThreeVector detectorPos, G4double detectorDimX, G4double detectorDimY, G4double detectorDimZ, G4int numberOfVoxelsX, G4int numberOfVoxelsY, G4int numberOfVoxelsZ)
double getY() const
static HadrontherapyDetectorConstruction * GetInstance()
#define G4BestUnit(a, b)
#define G4_USE_G4BESTUNIT_FOR_VERBOSE 1
void SetDetectorSize(G4double sizeX, G4double sizeY, G4double sizeZ)
int G4int
Definition: G4Types.hh:78
static G4NistManager * Instance()
static G4PhysicalVolumeStore * GetInstance()
string material
Definition: eplot.py:19
static HadrontherapyMatrix * GetInstance()
double getX() const
G4GLOB_DLL std::ostream G4cout
static constexpr double um
Definition: G4SIunits.hh:113
bool G4bool
Definition: G4Types.hh:79
static constexpr double cm
Definition: G4SIunits.hh:119
void SetDetectorToPhantomPosition(G4ThreeVector DetectorToPhantomPosition)
bool IsInside(G4double detectorX, G4double detectorY, G4double detectorZ, G4double phantomX, G4double phantomY, G4double phantomZ, G4ThreeVector pos)
G4VUserParallelWorld * GetParallelWorld(G4int i) const
static G4GeometryManager * GetInstance()
def SetMaterial
Definition: EmPlot.py:25
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
static G4RunManager * GetRunManager()
Definition: G4RunManager.cc:79
int G4lrint(double ad)
Definition: templates.hh:163
double getZ() const
#define G4endl
Definition: G4ios.hh:61
void InitializeDetectorROGeometry(HadrontherapyDetectorROGeometry *, G4ThreeVector detectorToWorldPosition)
double G4double
Definition: G4Types.hh:76
void SetVoxelSize(G4double sizeX, G4double sizeY, G4double sizeZ)
static const G4double pos