ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
IORTDetectorConstruction.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file IORTDetectorConstruction.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 // This is the *BASIC* version of IORT, a Geant4-based application
27 //
28 // Main Authors: G.Russo(a,b), C.Casarino*(c), G.C. Candiano(c), G.A.P. Cirrone(d), F.Romano(d)
29 // Contributor Authors: S.Guatelli(e)
30 // Past Authors: G.Arnetta(c), S.E.Mazzaglia(d)
31 //
32 // (a) Fondazione Istituto San Raffaele G.Giglio, Cefalù, Italy
33 // (b) IBFM-CNR , Segrate (Milano), Italy
34 // (c) LATO (Laboratorio di Tecnologie Oncologiche), Cefalù, Italy
35 // (d) Laboratori Nazionali del Sud of the INFN, Catania, Italy
36 // (e) University of Wollongong, Australia
37 //
38 // *Corresponding author, email to carlo.casarino@polooncologicocefalu.it
40 
41 #include <cmath>
42 #include "G4SystemOfUnits.hh"
43 #include "globals.hh"
44 #include "G4SDManager.hh"
45 #include "G4RunManager.hh"
46 #include "G4GeometryManager.hh"
47 #include "G4SolidStore.hh"
48 #include "G4PhysicalVolumeStore.hh"
49 #include "G4LogicalVolumeStore.hh"
50 #include "G4Box.hh"
51 #include "G4LogicalVolume.hh"
52 #include "G4ThreeVector.hh"
53 #include "G4PVPlacement.hh"
54 #include "G4Transform3D.hh"
55 #include "G4RotationMatrix.hh"
56 #include "G4Colour.hh"
57 #include "G4UserLimits.hh"
58 #include "G4UnitsTable.hh"
59 #include "G4VisAttributes.hh"
60 #include "G4NistManager.hh"
62 #include "G4Tubs.hh"
64 #include "G4VPrimitiveScorer.hh"
65 #include "G4PSDoseDeposit3D.hh"
66 #include "IORTDetectorMessenger.hh"
67 
70  : motherPhys(physicalTreatmentRoom), // pointer to WORLD volume
71  phantom(0), detector(0),
72  phantomLogicalVolume(0), detectorLogicalVolume(0),
73  phantomPhysicalVolume(0), detectorPhysicalVolume(0),
74  aRegion(0),
75 
76  solidDiscoIORT0(0),
77  logicDiscoIORT0(0),
78  physiDiscoIORT0(0),
79 
80  solidDiscoIORT(0),
81  logicDiscoIORT(0),
82  physiDiscoIORT(0),
83 
84  solidDiscoIORT1(0),
85  logicDiscoIORT1(0),
86  physiDiscoIORT1(0)
87 
88 {
89 
90  /* NOTE! that the IORTDetectorConstruction class
91  * does NOT inherit from G4VUserDetectorConstruction G4 class
92  * So the Construct() mandatory virtual method is inside another geometric class
93  * like the collimatorXXBeamLIne, ...
94  */
95 
96  // Messenger to change parameters of the phantom/detector geometry
98 
99  // Define here the material of the water phantom and of the detector
100  SetPhantomMaterial("G4_WATER");
101 
102  // Construct geometry (messenger commands)
103 
104  // Detector
105  // Default detector sizes
106  detectorSizeX = 7.* cm;
107  detectorSizeY = 15.* cm;
108  detectorSizeZ = 15.* cm;
109 
111 
112  // Phantom
113  SetPhantomSize(20. *cm, 20. *cm, 20. *cm);
114  SetPhantomPosition(G4ThreeVector(4.5 *cm, 0. *cm, 0. *cm));
116 
117  // Default protection disc geometry and materials
118  SetOuterRadiusDiscoIORT (40. *mm);
120  SetheightDiscoIORT (2.0*mm);
121  SetDiscoXPositionIORT (-11.0*mm);
124  SetDiscoMaterialIORT("G4_WATER");
125 
128  SetheightDiscoIORT1 (1.0*mm);
129  SetDiscoXPositionIORT1 (-8.0*mm);
130  SetDiscoMaterialIORT1("G4_WATER");
131 
132  SetAngleDiscoIORT0 (90.0 *deg);
133 
134  // Write virtual parameters to the real ones and check for consistency
135  UpdateGeometry();
136 }
137 
140 {
141  delete detectorMessenger;
142 }
143 
145 // ConstructPhantom() is the method that reconstuct a water box (called phantom
146 // (or water phantom)).
147 // A water phantom can be considered a good
148 // approximation of a an human body.
150 
152 {
153  // Definition of the solid volume of the Phantom
154  phantom = new G4Box("Phantom",
155  phantomSizeX/2,
156  phantomSizeY/2,
157  phantomSizeZ/2);
158 
159 // Definition of the logical volume of the Phantom
162  "phantomLog", 0, 0, 0);
163 
164  // Definition of the physics volume of the Phantom
167  "phantomPhys",
169  motherPhys,
170  false,
171  0);
172 
173 // Visualisation attributes of the phantom
174  red = new G4VisAttributes(G4Colour(255/255., 0/255. ,0/255.));
175  red -> SetVisibility(true);
176  //red -> SetForceSolid(true);
177  //red -> SetForceWireframe(true);
178  phantomLogicalVolume -> SetVisAttributes(red);
179  //phantomLogicalVolume -> SetVisAttributes(G4VisAttributes::GetInvisible());
180 }
181 
183 // ConstructDetector() it the method the reconstruct a detector region
184 // inside the water phantom. It is a volume, located inside the water phantom
185 // and with two coincident faces:
186 //
187 // **************************
188 // * water phantom *
189 // * *
190 // * *
191 // *--------------- *
192 // Beam * - *
193 // -----> * detector - *
194 // * - *
195 // *--------------- *
196 // * *
197 // * *
198 // * *
199 // **************************
200 //
201 // The detector is the volume that can be dived in slices or voxelized
202 // and in it we can collect a number of usefull information:
203 // dose distribution, fluence distribution, LET and so on
204 
206 {
207 
208  // Definition of the solid volume of the Detector
209  detector = new G4Box("Detector",
210  detectorSizeX/2,
211  detectorSizeY/2,
212  detectorSizeZ/2);
213 
214  // Definition of the logic volume of the Phantom
217  "DetectorLog",
218  0,0,0);
219 // Definition of the physical volume of the Phantom
221  detectorPosition, // Setted by displacement
222  "DetectorPhys",
225  false,0);
226 
227 // Visualisation attributes of the detector
228 
229  G4VisAttributes * skyBlue1 = new G4VisAttributes( G4Colour(135/255. , 206/255. , 235/255. ));
230  detectorLogicalVolume -> SetVisAttributes(skyBlue1);
231 
232  // **************
233  // Cut per Region
234  // **************
235 
236  // A smaller cut is fixed in the phantom to calculate the energy deposit with the
237  // required accuracy
238  if (!aRegion)
239  {
240  aRegion = new G4Region("DetectorLog");
241  detectorLogicalVolume -> SetRegion(aRegion);
242  aRegion -> AddRootLogicalVolume(detectorLogicalVolume);
243  }
244  G4cout << "The Detector has been built --- Add a scoring mesh for it in the GUI if appropriate (similar to the phantom one)" << G4endl;
245 
246 }
247 
249 {
250 // ---------------------------------------------------------------//
251  // 6.0 mm Protection Discs Volume //
252  // ---------------------------------------------------------------//
253  const G4double startAngleDiscoIORT0 = 0.*deg;
254  const G4double spanningAngleDiscoIORT0 = 360.*deg;
255 
256  // Matrix definition for a rotation (deg).
257  G4RotationMatrix rm0;
259 
260 
261  solidDiscoIORT0 = new G4Tubs("DiscoIORT0", innerRadiusDiscoIORT,
264  startAngleDiscoIORT0,
265  spanningAngleDiscoIORT0);
266 
267  G4LogicalVolume* logDiscoIORT0 = new G4LogicalVolume(solidDiscoIORT0,
268  detectorMaterial, "DiscoIORT0Log", 0, 0, 0);
269 
271  "DiscoIORT0Phys", logDiscoIORT0, detectorPhysicalVolume, false, 0);
272 
273  white = new G4VisAttributes( G4Colour());
274  white -> SetVisibility(true);
275  // white -> SetForceSolid(true);
276  logDiscoIORT0 -> SetVisAttributes(white);
277 
278 // ---------------------------------------------------------------//
279  // 4.0 mm Aluminium Protection Disc //
280  // ---------------------------------------------------------------//
281  //G4bool isotopes = false;
282  // G4Material* leadNist = G4NistManager::Instance()->FindOrBuildMaterial("G4_Pb", isotopes);
283  // DiscoMaterialIORT = leadNist; // messenger
284  gray = new G4VisAttributes( G4Colour(0.5, 0.5, 0.5 ));
285  gray-> SetVisibility(true);
286  //gray -> SetForceWireframe(true);
287  //gray-> SetForceSolid(true);
288 
289  gray1 = new G4VisAttributes( G4Colour(0.7, 0.7, 0.7 ));
290  gray1-> SetVisibility(true);
291  //gray1 -> SetForceWireframe(true);
292  //gray1-> SetForceSolid(true);
293 
294  const G4double startAngleDiscoIORT = 0.*deg;
295  const G4double spanningAngleDiscoIORT = 360.*deg;
296 
297  G4double phi = 0. *deg;
298 
299  // Matrix definition for a 90 deg rotation. Also used for other volumes
300  G4RotationMatrix rm;
301  rm.rotateY(phi);
302 
303  solidDiscoIORT = new G4Tubs("DiscoIORT", innerRadiusDiscoIORT,
306  startAngleDiscoIORT,
307  spanningAngleDiscoIORT);
308 
309  G4LogicalVolume* logDiscoIORT = new G4LogicalVolume(solidDiscoIORT,
310  DiscoMaterialIORT, "DiscoIORTLog", 0, 0, 0);
311 
313  "DiscoIORTPhys", logDiscoIORT, physiDiscoIORT0, false, 0);
314 
315  logDiscoIORT -> SetVisAttributes(gray1);
316 
317 
318  // ---------------------------------------------------------------//
319  // 2.0 mm Lead Protection Disc //
320  // ---------------------------------------------------------------//
321 
322  const G4double startAngleDiscoIORT1 = 0.*deg;
323  const G4double spanningAngleDiscoIORT1 = 360.*deg;
324 
325  solidDiscoIORT1 = new G4Tubs("DiscoIORT1", innerRadiusDiscoIORT1,
328  startAngleDiscoIORT1,
329  spanningAngleDiscoIORT1);
330 
331  G4LogicalVolume* logDiscoIORT1 = new G4LogicalVolume(solidDiscoIORT1,
332  DiscoMaterialIORT1, "DiscoIORTLog1", 0, 0, 0);
333 
335  "DiscoIORTPhys1", logDiscoIORT1, physiDiscoIORT0, false, 0);
336  white = new G4VisAttributes( G4Colour());
337  white -> SetVisibility(true);
338  white -> SetForceSolid(true);
339  logDiscoIORT1 -> SetVisAttributes(gray);
340 
341 }
343 
345 {
346  // Check phantom/detector sizes & relative position
347  if (!IsInside(detectorSizeX,
348  detectorSizeY,
350  phantomSizeX,
351  phantomSizeY,
352  phantomSizeZ,
354  ))
355  G4Exception("IORTDetectorConstruction::ParametersCheck()", "IORT0001", FatalException, "Error: Detector is not fully inside Phantom!");
356 }
357 
359 // MESSENGERS //
361 
363 {
364 
365  if (G4Material* pMat = G4NistManager::Instance()->FindOrBuildMaterial(material, false) )
366  {
367  phantomMaterial = pMat;
368  detectorMaterial = pMat;
370  {
373 
374  G4RunManager::GetRunManager() -> PhysicsHasBeenModified();
376  G4cout << "The material of Phantom/Detector has been changed to " << material << G4endl;
377  }
378  }
379  else
380  {
381  G4cout << "WARNING: material \"" << material << "\" doesn't exist in NIST elements/materials"
382  " table [located in $G4INSTALL/source/materials/src/G4NistMaterialBuilder.cc]" << G4endl;
383  G4cout << "Use command \"/parameter/nist\" to see full materials list!" << G4endl;
384  return false;
385  }
386 
387  return true;
388 }
389 
391 {
392 
393  if (G4Material* dMat = G4NistManager::Instance()->FindOrBuildMaterial(material, false) )
394  {
395  DiscoMaterialIORT = dMat;
396 
397  if (logicDiscoIORT)
398  {
399  logicDiscoIORT -> SetMaterial(dMat);
400 
401  G4RunManager::GetRunManager() -> PhysicsHasBeenModified();
403  G4cout << "The material of Protection disc 1 has been changed to " << material << G4endl;
404  }
405  }
406  else
407  {
408  G4cout << "WARNING: material \"" << material << "\" doesn't exist in NIST elements/materials"
409  " table [located in $G4INSTALL/source/materials/src/G4NistMaterialBuilder.cc]" << G4endl;
410  G4cout << "Use command \"/parameter/nist\" to see full materials list!" << G4endl;
411  return false;
412  }
413 
414  return true;
415 }
416 
418 {
419 
420  if (G4Material* d1Mat = G4NistManager::Instance()->FindOrBuildMaterial(material, false) )
421  {
422  DiscoMaterialIORT1 = d1Mat;
423 
424  if (logicDiscoIORT1)
425  {
426  logicDiscoIORT1 -> SetMaterial(d1Mat);
427 
428  G4RunManager::GetRunManager() -> PhysicsHasBeenModified();
430  G4cout << "The material of Protection disc 2 has been changed to " << material << G4endl;
431  }
432  }
433  else
434  {
435  G4cout << "WARNING: material \"" << material << "\" doesn't exist in NIST elements/materials"
436  " table [located in $G4INSTALL/source/materials/src/G4NistMaterialBuilder.cc]" << G4endl;
437  G4cout << "Use command \"/parameter/nist\" to see full materials list!" << G4endl;
438  return false;
439  }
440 
441  return true;
442 }
445 {
446  if (sizeX > 0.) phantomSizeX = sizeX;
447  if (sizeY > 0.) phantomSizeY = sizeY;
448  if (sizeZ > 0.) phantomSizeZ = sizeZ;
449 }
453 {
454  if (sizeX > 0.) {detectorSizeX = sizeX;}
455  if (sizeY > 0.) {detectorSizeY = sizeY;}
456  if (sizeZ > 0.) {detectorSizeZ = sizeZ;}
457 }
459 
461 {
462  G4cout<< "SetVoxelSize method is not needed anymore " << G4endl;
463 }
465 {
467 }
468 
471 {
473 }
475 
477 {
478  if (outerr > 0.) {OuterRadiusDiscoIORT = outerr;}
479 
480 }
481 
483 {
484  if (innerr >= 0.) {innerRadiusDiscoIORT = innerr;}
485 
486 }
487 
489 {
490  if (height > 0.) {heightDiscoIORT = height;}
491 
492 }
493 
495 {
496 
497  DiscoXPositionIORT = xpos;
498 
499 }
500 
502 {
503 
504  DiscoYPositionIORT = ypos;
505 
506 }
507 
509 {
510 
512 
513 }
514 
516 {
517  if (outerr > 0.) {OuterRadiusDiscoIORT1 = outerr;}
518 
519 }
520 
522 {
523  if (innerr >= 0.) {innerRadiusDiscoIORT1 = innerr;}
524 
525 }
526 
528 {
529  if (height > 0.) {heightDiscoIORT1 = height;}
530 
531 }
532 
534 {
535 
536  DiscoXPositionIORT1 = xpos;
537 }
538 
540 {
541 
542  AngleDiscoIORT0 = phi0;
543 }
544 
546 
547 
550 {
551  /*
552  * Check parameters consistency
553  */
554  ParametersCheck();
555 
556  G4GeometryManager::GetInstance() -> OpenGeometry();
557  if (phantom)
558  {
559  phantom -> SetXHalfLength(phantomSizeX/2);
560  phantom -> SetYHalfLength(phantomSizeY/2);
561  phantom -> SetZHalfLength(phantomSizeZ/2);
562  phantomPhysicalVolume -> SetTranslation(phantomPosition);
563  }
564  else ConstructPhantom();
565 
566  // Get the center of the detector
568  if (detector)
569  {
570  detector -> SetXHalfLength(detectorSizeX/2);
571  detector -> SetYHalfLength(detectorSizeY/2);
572  detector -> SetZHalfLength(detectorSizeZ/2);
573  detectorPhysicalVolume -> SetTranslation(detectorPosition);
574  }
575  else ConstructDetector();
576 
577  // update disc function
578  if (physiDiscoIORT1) delete physiDiscoIORT1;
579  if (logicDiscoIORT1) delete logicDiscoIORT1;
580  if (solidDiscoIORT1) delete solidDiscoIORT1;
581 
582  if (physiDiscoIORT) delete physiDiscoIORT;
583  if (logicDiscoIORT) delete logicDiscoIORT;
584  if (solidDiscoIORT) delete solidDiscoIORT;
585 
586  if (physiDiscoIORT0) delete physiDiscoIORT0;
587  if (logicDiscoIORT0) delete logicDiscoIORT0;
588  if (solidDiscoIORT0) delete solidDiscoIORT0;
589 
590  ConstructDisc();
591 
592  // Inform the kernel about the new geometry
594  G4RunManager::GetRunManager() -> PhysicsHasBeenModified();
595 
596  PrintParameters();
597 }
598 
600 {
601  if (physiDiscoIORT1) delete physiDiscoIORT1;
602  if (logicDiscoIORT1) delete logicDiscoIORT1;
603  if (solidDiscoIORT1) delete solidDiscoIORT1;
604 
605  if (physiDiscoIORT) delete physiDiscoIORT;
606  if (logicDiscoIORT) delete logicDiscoIORT;
607  if (solidDiscoIORT) delete solidDiscoIORT;
608 
609  if (physiDiscoIORT0) delete physiDiscoIORT0;
610  if (logicDiscoIORT0) delete logicDiscoIORT0;
611  if (solidDiscoIORT0) delete solidDiscoIORT0;
612 
614  G4RunManager::GetRunManager() -> PhysicsHasBeenModified();
615 }
616 
617 
619 {
620 
621  G4cout << "The (X,Y,Z) dimensions of the phantom are : (" <<
622  G4BestUnit( phantom -> GetXHalfLength()*2., "Length") << ',' <<
623  G4BestUnit( phantom -> GetYHalfLength()*2., "Length") << ',' <<
624  G4BestUnit( phantom -> GetZHalfLength()*2., "Length") << ')' << G4endl;
625 
626  G4cout << "The (X,Y,Z) dimensions of the detector are : (" <<
627  G4BestUnit( detector -> GetXHalfLength()*2., "Length") << ',' <<
628  G4BestUnit( detector -> GetYHalfLength()*2., "Length") << ',' <<
629  G4BestUnit( detector -> GetZHalfLength()*2., "Length") << ')' << G4endl;
630 
631  G4cout << "Displacement between Phantom and World is: ";
632  G4cout << "DX= "<< G4BestUnit(phantomPosition.getX(),"Length") <<
633  "DY= "<< G4BestUnit(phantomPosition.getY(),"Length") <<
634  "DZ= "<< G4BestUnit(phantomPosition.getZ(),"Length") << G4endl;
635 }
636