ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
doiPETDetectorConstruction.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file doiPETDetectorConstruction.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 //GEANT4 - Depth-of-Interaction enabled Positron emission tomography (PET) advanced example
27 
28 //Authors and contributors
29 
30 // Author list to be updated, with names of co-authors and contributors from National Institute of Radiological Sciences (NIRS)
31 
32 // Abdella M. Ahmed (1, 2), Andrew Chacon (1, 2), Harley Rutherford (1, 2),
33 // Hideaki Tashima (3), Go Akamatsu (3), Akram Mohammadi (3), Eiji Yoshida (3), Taiga Yamaya (3)
34 // Susanna Guatelli (2), and Mitra Safavi-Naeini (1, 2)
35 
36 // (1) Australian Nuclear Science and Technology Organisation, Australia
37 // (2) University of Wollongong, Australia
38 // (3) National Institute of Radiological Sciences, Japan
39 
40 
41 
42 //A whole-body PET scanner with depth-of-intercation (DOI) detector is
43 //defined in the doiPETDetectorConstruction class and varius types phantoms
44 //are also defined based on the NEMA NU-2 2012 standard protocol for
45 //performance evaluation PET scanners.
46 //The scanner's geometrical specifications (like number of crystals, number of rings ...) are defined as a global variable in the doiPETGlobalParameters.hh
47 //If the phantom is other there the phantoms defined, exception will be thrown. If you want to run the simulation without phantom (for any reason),
48 //you can comment out ConstructPhantom(world_logicalV) method.
49 
51 #include "doiPETAnalysis.hh"
54 
55 #include "G4NistManager.hh"
56 #include "G4Box.hh"
57 #include "G4Tubs.hh"
58 #include "G4LogicalVolume.hh"
59 #include "G4PVPlacement.hh"
60 #include "G4RotationMatrix.hh"
61 #include "G4Transform3D.hh"
62 #include "G4SDManager.hh"
64 #include "G4VPrimitiveScorer.hh"
65 #include "G4PSEnergyDeposit.hh"
66 #include "G4PSDoseDeposit.hh"
67 #include "G4VisAttributes.hh"
68 #include "G4PhysicalConstants.hh"
69 #include "G4SystemOfUnits.hh"
70 
71 //
72 #include "G4SubtractionSolid.hh"
73 #include "G4UnionSolid.hh"
74 #include "G4IntersectionSolid.hh"
75 //
76 #include "G4Element.hh"
77 #include "G4Material.hh"
78 #include "G4Sphere.hh"
79 #include "G4Colour.hh"
80 #include "G4RunManager.hh"
81 #include "G4StateManager.hh"
82 #include "G4GeometryManager.hh"
83 #include "G4PhysicalVolumeStore.hh"
84 #include "G4LogicalVolumeStore.hh"
85 #include "G4SolidStore.hh"
86 
87 
89 
92  fCheckOverlaps(true)
93 {
96 
97  //Initialize variables. The following variables can be changed via the run.mac file.
98  PhantomType = "NEMA_phantom_NECR";
99  phantomRadius = 100 * mm;
100  phantomLength = 700 * mm;
102 }
103 
105 
107 {
108  delete fDetectorMessenger;
109 }
110 
112 
114 {
116 
117  //Define air
118  air = nist->FindOrBuildMaterial("G4_AIR");
119 
120  //Define PMMA
121  pmma = nist->FindOrBuildMaterial("G4_PLEXIGLASS"); //Default 1.19 g/cm3
122 
123  //Define water
124  water = nist->FindOrBuildMaterial("G4_WATER");
125 
126  //Defining polyethylene from NIST and modifying the density
127  polyethylene = nist->BuildMaterialWithNewDensity("polyethylene","G4_POLYETHYLENE",0.959*g/cm3);
129 
130  //polyethylene_NEMA, defualt density 0.94 g/cm3, and excitation energy = 57.4 eV
131  polyethylene_NEMA = nist->FindOrBuildMaterial("G4_POLYETHYLENE");
132 
133 
134  //Define expanded polystyrene by modifiying the density to mimic lung phantom used in phantom experiment
135  polystyrene = nist->BuildMaterialWithNewDensity( "polystyrene","G4_POLYSTYRENE",0.3*g/cm3);
136 
137  isotopes = false;
138 
139  //Defile Aluminum material for the detetor cover
140  Aluminum = nist->FindOrBuildMaterial("G4_Al", isotopes);
141 
142  //Define elements for the GSO crystal (scintillator)
143  O = nist->FindOrBuildElement("O" , isotopes);
144  Si = nist->FindOrBuildElement("Si", isotopes);
145  Gd = nist->FindOrBuildElement("Gd", isotopes);
146 
147 
148  //define GSO crystal for PET detector
149  GSO = new G4Material("GSO", 6.7*g/cm3, 3);
150  GSO->AddElement(Gd, 2);
151  GSO->AddElement(Si, 1);
152  GSO->AddElement(O, 5);
153  crystalMaterial = nist->FindOrBuildMaterial("GSO");
154 }
155 
157 
159 {
160 
161 
162  //size of the world
163  worldSizeX = 2 * m;//0.5 *mm
164  worldSizeY = 2 * m;//0.5*mm
165  worldSizeZ = 4. * m;
166 
167 
168  // Define a solid shape to describe the world volume
169  G4Box* solid_world = new G4Box("world", worldSizeX/2., worldSizeY/2., worldSizeZ/2.);
170 
171  // Define a logical volume for the world volume
172  world_logicalV = new G4LogicalVolume(solid_world, air, "world_logicalV", 0,0,0);
173 
174 
175  // Define the physical world volume
176  world_physicalV = new G4PVPlacement(0,G4ThreeVector(),world_logicalV, "world_physicalV", 0, false, 0, fCheckOverlaps);
178 
179  //NOTE!!!
180  //The scanner specification (like size and number of crystals in each detctor) are given in the "doiPETGlobalParameters.hh" header file.
181 
182  //Each block detector is identified with its unique number, blockIndex.
183  blockIndex = 0;
184 
185  //Each crystal is identified with its unique number, crystalIndex
186  crystalIndex = 0;
187 
188  //This is to place the phantom.
189 
191 
192  //Define air volume (box) to fill the detector block. Crystal elements (scintillators) is then placed.
196 
197  //This will pass the size of the detector block so that the position of the PMT will be calculated with respect to the axis of the detector block.
198  //see doiPETAnalysis.cc
201 
202  G4cout<<"size of crytal element: "<<sizeOfCrystal_tangential<<" "<<sizeOfCrystal_axial<<" "<<sizeOfCrystal_DOI<<G4endl;
203  G4cout<<"Size of detector block (without Al cover): "<<sizeOfAirBox_tangential<<" "<<sizeOfAirBox_axial<<" "<<sizeOfAirBox_DOI<<G4endl;
204 
205 
206 
207  //Define the size of the detector block.
211 
212 
213 
214  //Define solid shape for the detector block
216 
217  //Define the logical volume for the detector block
218  blockDetector_logicalV = new G4LogicalVolume(blockDetector,Aluminum,"blockDetector_logicalV", 0,0,0);
219 
220 
221 
222  //Define air (box) inside the detector block. Crystal elements will be placed in it.
224 
225  //Define the logical volume
226  airBox_logicalV = new G4LogicalVolume(airBox,air,"airBox_logicalV", 0,0,0);
227 
228  //Define its physical volume and place it inside the detector block
230 
231 
233 
234  for(G4int Ring = 0; Ring< numberOfRings; Ring++)
235  {
236  //place the detectors in a ring along the axial direction. Note that the ring gap between two adjcent rings is measured from scintillator to scintillator. It does not include the Aluminum thickness cover.
237 
239 
240  for(G4int i = 0; i<numberOfDetector_perRing; i++)
241  {
242  //The azimuthal angle to arrange the detectors in a ring
243  thetaDetector = (double)(i*twopi/numberOfDetector_perRing);
244 
245  //The radius of the scanner is measured from opposing crystal (scintillator) faces. It does not include the Aluminum thickness cover.
246  detectorPositionX = (scannerRadius + sizeOfBlockDetector_DOI/2 - AluminumCoverThickness/2)*std::cos(thetaDetector);
247  detectorPositionY = (scannerRadius + sizeOfBlockDetector_DOI/2 - AluminumCoverThickness/2)*std::sin(thetaDetector);
248 
249  //Define the rotation matrix for correct placement of detetors
250  G4RotationMatrix rotm_PET = G4RotationMatrix();
251  rotm_PET.rotateZ(thetaDetector);
253  G4Transform3D transform = G4Transform3D(rotm_PET,uz_PET);
254 
255  //Define the physical volume of the detectors.
256  blockDetector_physicalV = new G4PVPlacement (transform,blockDetector_logicalV,"blockDetector_physicalV", world_logicalV,false,blockIndex,fCheckOverlaps);
257  blockIndex++;
258  //G4cout<<Ring<<" "<<detectorPositionX- ((sizeOfBlockDetector_DOI - AluminumCoverThickness)/2)*cos(thetaDetector)<<" "<<detectorPositionY- ((sizeOfBlockDetector_DOI- AluminumCoverThickness)/2)*sin(thetaDetector)<<" "<<detectorPositionZ<<G4endl;
259 
260  }
261  }
262 
263  //Define the solid crystal
264  G4VSolid* CrystalSolid = new G4Box("Crystal", sizeOfCrystal_DOI/2., sizeOfCrystal_tangential/2., sizeOfCrystal_axial/2.);
265 
266  //Define the local volume of the crystal
267  crystal_logicalV = new G4LogicalVolume(CrystalSolid,crystalMaterial,"Crystal_logicalV", 0,0,0);
268 
269  //Place the crystals inside the detectors and give them a unique number with crystalIndex.
270  for(G4int i_DOI = 0; i_DOI<numberOfCrystal_DOI; i_DOI++){
271  crystalPositionX=(i_DOI-((G4double)numberOfCrystal_DOI)/2 + 0.5)*(sizeOfCrystal_DOI + crystalGap_DOI);
272  for(G4int i_axial=0; i_axial< numberOfCrystal_axial;i_axial++){
273  crystalPositionZ = (i_axial-((G4double)numberOfCrystal_axial)/2 + 0.5)*(sizeOfCrystal_axial + crystalGap_axial);
274  for(G4int i_tan=0; i_tan<numberOfCrystal_tangential;i_tan++){
275  crystalPositionY=(i_tan-((G4double)numberOfCrystal_tangential)/2 + 0.5)*(sizeOfCrystal_tangential + crystalGap_tangential);
276 
277  //G4cout<<crystalIndex<<" "<<crystalPositionX<<" "<<crystalPositionY<<" "<<crystalPositionZ<<G4endl;
278  //place the crystal inside the block detector.
280  crystalIndex++;
281  }
282  }
283  }
284 
285  //****************** Visualization *****************************//
286 
287  //visualization for the block detector
288  G4VisAttributes* blockDetectorVisAtt;
289  blockDetectorVisAtt = new G4VisAttributes(G4Colour(1,1.0,1.0));
290  blockDetectorVisAtt->SetVisibility (true);
291  //blockDetectorVisAtt->SetForceWireframe (true);
292  blockDetector_logicalV->SetVisAttributes (blockDetectorVisAtt);
293  //blockDetector_logicalV->SetVisAttributes (G4VisAttributes::Invisible);
294 
295  //visualization for the the box filled with air
296  G4VisAttributes* airBoxVisAtt;
297  airBoxVisAtt = new G4VisAttributes(G4Colour(1,1.0,1.0));
298  airBoxVisAtt->SetVisibility (true);
299  airBoxVisAtt->SetForceWireframe (true);
300  airBox_logicalV->SetVisAttributes (airBoxVisAtt);
302 
303  //visualization for the crystal
304  G4VisAttributes* crystalVisAtt;
305  crystalVisAtt = new G4VisAttributes(G4Colour(0.88,0.55,1.0));
306  //crystalVisAtt->SetVisibility (true);
307  crystalVisAtt->SetForceWireframe (true);
308  crystal_logicalV->SetVisAttributes (crystalVisAtt);
310 
311 
312  //always return the physical World
313  return world_physicalV;
314 }
315 
316 
318 
320 {
321  G4cout<<"------------------================- " <<PhantomType<<" Phantom has been used -==================-----------\n"<<G4endl;
322 
323  //The following phantoms are defined based on NEMA NU-2 Standards Publication (Performance Measurements of Positron Emission Tomographs)
324  if(PhantomType == "NEMA_imageQualityPhantom_wholeBody"){
325 
326  //The body phantom (also called image quality phantom) can presisely be created by the G4UninSolid method from (1) one big half cylinder (with a diameter of 150 mm),
327  //(2) two small full (or quarter) cylinders (with 80mm), and (3) a box with a height width of 140 mm and height of 80mm.
328  //All the material to surround (hold) the water is PMMA.
329 
330  //offset position for the body phantom. The center of the body phantom is mover by 35 mm in the +y direction
331  yOffsetBodyPhantom = 35*mm;
332 
333  //The body phantom is moved by 70 mm in the z direction so that the sphere (cold and hot spheres) are coplanar with the middle slice of the scanner
335 
336  //length (in the z-direction) of the body phantom.
337  lengthOfBodyPhantom = 180*mm; //Interior length ( = 180m mm) + wallthickness (= 3mm)
338 
339  //outer radius of the body phantom. (inner radius + wallthinkness)
340  radiusOfBodyPhantom = 147 * mm;
341 
342  //wall thickness of the surrounding pmma phantom
344 
345  //
346  radiusOfSmallcyl = 77 * mm;
347  boxWidth = 140*mm;// along the x-axis
348  boxHeight = 77 * mm; // along the y-axis
349 
350 
351  /************************* Surrounding PMMA ***********************************/
352 
353  //define a half cylinder
355 
356  //define two full small cylinder. (It can be also be a quarter or half).
359 
360  //define a box
362 
363  //a translation vector for the small cylinder with respect to the half cylinder at position (70 mm,0,0)
364  G4ThreeVector translation_cyl1 = G4ThreeVector(boxWidth/2, 0, 0);
365 
366  //a translation vector for the small cylinder with respect to the half cylinder at position (-70 mm,0,0)
367  G4ThreeVector translation_cyl2 = G4ThreeVector(-boxWidth/2, 0, 0);
368 
369  //translation for the box with respect to half cylinder
370  G4ThreeVector translation_box = G4ThreeVector(0,-(boxHeight + wallThicknessOfBodyPhantom)/2, 0);
371 
372  //define union1_pmma by uniting the solids of halfcyl and cyl1
373  G4UnionSolid* union1_pmma = new G4UnionSolid("union1",halfcyl_pmma,cyl1_pmma,0,translation_cyl1);
374 
375  //define union2_pmma by uniting the solids of union1_pmma and cyl2
376  G4UnionSolid* union2_pmma = new G4UnionSolid("union2",union1_pmma,cyl2_pmma,0,translation_cyl2);
377 
378  //********** Now define the solid volume of the surrounding PMMA body phantom *********//
379  //define phantom by uniting the solids of union2_pmma and box_pmma
380  G4UnionSolid* phantom = new G4UnionSolid("phantom",union2_pmma,box_pmma,0,translation_box);
381 
382  //Define the logical volume of the body phantom
383  phantom_logicalV = new G4LogicalVolume(phantom, pmma, "phantom_logicalV",0,0,0);
384 
385  //Define the physical volume of the body phantom
387 
388 
389 
390  //****************************** Water inside the PMMA phantom ********************************/
391 
392  //define a half cylinder
393  G4Tubs* halfcyl_water = new G4Tubs("halfcyl_water", 0*mm,radiusOfBodyPhantom,lengthOfBodyPhantom/2,0*deg,180*deg);
394 
395  //define a full small cylinder phantom. (It can be also be a quarter or half).
396  G4Tubs* cyl1_water = new G4Tubs("cyl_water", 0*mm,radiusOfSmallcyl, lengthOfBodyPhantom/2,0*deg,360*deg);
397  G4Tubs* cyl2_water = new G4Tubs("cyl_water", 0*mm,radiusOfSmallcyl, lengthOfBodyPhantom/2,0*deg,360*deg);
398 
399  //define a box
400  G4Box* box_water = new G4Box("box_water", boxWidth/2, boxHeight/2, lengthOfBodyPhantom/2);
401 
402  //a translation vector for the small cylinder with respect to the half cylinder at position (70 mm,0,0)
403  G4ThreeVector translation_cyl1_water = G4ThreeVector(boxWidth/2, 0, 0);
404 
405  //a translation vector for the small cylinder with respect to the half cylinder at position (-70 mm,0,0)
406  G4ThreeVector translation_cyl2_water = G4ThreeVector(-boxWidth/2, 0, 0);
407 
408  //translation for the box with respect to half cylinder
409  G4ThreeVector translation_box_water = G4ThreeVector(0,-boxHeight/2, 0);
410 
411  //define union1_water by uniting the solids of halfcyl and cyl1
412  G4UnionSolid* union1_water = new G4UnionSolid("union1",halfcyl_water,cyl1_water,0,translation_cyl1_water);
413 
414  //define union2_water by uniting the solids of union1_water and cyl2
415  G4UnionSolid* union2_water = new G4UnionSolid("union2",union1_water,cyl2_water,0,translation_cyl2_water);
416 
417  //********** Now define the solid volume of the body phantom to be filled with water *********//
418  //define phantom by uniting the solids of union2_water and box_water
419  G4UnionSolid* phantom_water = new G4UnionSolid("phantom_water",union2_water,box_water,0,translation_box_water);
420 
421  //Define the logical volume of the body phantom
422  water_logicalV = new G4LogicalVolume(phantom_water, water, "phantom_logicalV",0,0,0);
423 
424  //Define the physical volume of the body phantom
425  water_physicalV = new G4PVPlacement(0, G4ThreeVector(0,0,0), water_logicalV, "phantom_physicalV", phantom_logicalV, false, 0, fCheckOverlaps);
426 
427  //
429 
430  //A lung phantom (with low density material) is inserted in the body phantom.
431  G4double wallThiknessOfLungPhantom = 4 *mm;
432  radiusOfLungPhantom = 21 *mm;
433 
434  //define surrounding pmma phantom for the lung
435  //Define the solid shape for the lung phantom
436  G4Tubs* phantom_lungPMMA = new G4Tubs("Phantom_lung", 0*mm, radiusOfLungPhantom + wallThiknessOfLungPhantom,lengthOfBodyPhantom/2,0*deg,360*deg);
437 
438  //Define the logical volume of for the lung phantom
439  lung_logicalV_PMMA = new G4LogicalVolume(phantom_lungPMMA, pmma, "coldRegion_logicalV",0,0,0);
440 
441  //Define the physical volume for the lung phantom. The center of the lung phantom is moved (in the y-axis) by the same distance as that of the body phantom.
443 
444 
445  //Define the solid shape for the lung phantom
446  G4Tubs* phantom_lung = new G4Tubs("Phantom_lung", 0*mm,radiusOfLungPhantom,lengthOfBodyPhantom/2,0*deg,360*deg);
447 
448  //Define the logical volume of for the lung phantom
449  lung_logicalV = new G4LogicalVolume(phantom_lung, polystyrene, "coldRegion_logicalV",0,0,0);
450 
451  //Define the physical volume for the lung phantom and place it in the phantom_lungPMMA.
452  lung_physicalV = new G4PVPlacement(0, G4ThreeVector(0,0,0), lung_logicalV, "coldRegion_physicalV", lung_logicalV_PMMA, false, 0, fCheckOverlaps);
453  //lung_logicalV->SetVisAttributes (G4VisAttributes::Invisible);
454 
455 
457  //This phantom has the same characteristics with that of NECR phantom except its axial position.
458 
459  hieghtOfTestPhantom = 705* mm;
460  diameterOfTestPhantom = 203 * mm;
461  G4double zOffset_testPhantom = 0*mm;//this is to make some gap between the phantoms if necessary
462 
463  //Define the solid shape for the test phantom
464  G4Tubs* phantom_test = new G4Tubs("Phantom", 0*mm,diameterOfTestPhantom/2,hieghtOfTestPhantom/2,0*deg,360*deg);
465 
466  //Define the logical volume of the test phantom
467  test_logicalV = new G4LogicalVolume(phantom_test, polyethylene_NEMA, "phantom_logicalV",0,0,0);
468 
469  //Define the physical volume of the test phantom. The test phantom is placed next to the body phantom.
470  test_physicalV = new G4PVPlacement(0,G4ThreeVector(0,0,hieghtOfTestPhantom/2+zOffsetBodyPhantom + zOffset_testPhantom), test_logicalV, "phantom_physicalV", worldLogical, false, 0,fCheckOverlaps);
471  //test_logicalV->SetVisAttributes (G4VisAttributes::Invisible);
472 
474 
475  //Define diameter from the center of the body phantom to the center of the spheres
476  distanceFromCenter = 114.4*mm;
477 
478  //Define total number of spherical phantoms (both hot and cold spheres)
479  numberOfSpheres = 6;
480 
481  //Define the wall thickness of the spherical phantoms. It should be less than or equal to 1 mm according to the NEMA NU-2 protocol.
483 
484  //The centers of the sphere phantoms are placed 68 mm from the endplate of the body phantom so that the plane through the centers of the spheres is coplanar with to the middile slice of the scanner
486 
487  //Place the spherical phantoms in the body phantom
488  for(G4int i = 0; i < numberOfSpheres; i++){
489  if(i == 0) sphereDiameter = 37*mm;//cold sphere
490  if(i == 1) sphereDiameter = 10*mm;// hot sphere
491  if(i == 2) sphereDiameter = 13*mm;// hot sphere
492  if(i == 3) sphereDiameter = 17*mm;// hot sphere
493  if(i == 4) sphereDiameter = 22*mm;// hot sphere
494  if(i == 5) sphereDiameter = 28*mm;// cold sphere
495 
496  spherePositionX = distanceFromCenter/2*std::cos(((G4double)i*twopi/numberOfSpheres));
497  spherePositionY = distanceFromCenter/2*std::sin(((G4double)i*twopi/numberOfSpheres));
498  //zOffsetBodyPhantom = 0;
499 
500  //hot sphere phantoms
501  if(i>0 && i <5){
502 
503  //Surrounding PMMA phantom for the hot sphere
504  //Define the solid shape for the surrounding PMMA phantom for the hot sphere pahntom
505  G4Sphere* hotSpherePMMA = new G4Sphere("hotSphere", 0., sphereDiameter/2 + sphereWallThickness, 0*deg, 360*deg, 0*deg, 180*deg);
506 
507  //Deifne the logical volume of the surrounding PMMA for the hot sphere phantom
508  hotSpherePMMA_logicalV = new G4LogicalVolume(hotSpherePMMA, pmma , "hotSphere_logicalV",0,0,0);
509 
510  //Deifne the physical volume of the surrounding PMMA for the hot sphere phantom
512 
513 
514  //Defining and placing the water in the surrounding PMMA for hot sphere
515  //Define the solid shape of the water phantom for the hot sphere phantom
516  G4Sphere* hotSphereWater = new G4Sphere("hotSphere", 0., sphereDiameter/2, 0*deg, 360*deg, 0*deg, 180*deg);
517 
518  //Define the logical volume of the water phatom for the hot sphere
519  hotSphereWater_logicalV = new G4LogicalVolume(hotSphereWater, water , "hotSphere_logicalV",0,0,0);
520 
521  //Define the physical volume of the water phatom for the hot sphere
523  //G4cout<<"Hot sphere "<<i<<" is placed. "<< " sphereDiameter = " <<sphereDiameter <<" "<< "Position " <<spherePositionX<<" "<< spherePositionY<<", "<<sphereDiameter<<G4endl;
524  //hotSpherePMMA_logicalV->SetVisAttributes (G4VisAttributes::Invisible);
525  //hotSphereWater_logicalV->SetVisAttributes (G4VisAttributes::Invisible);
526  }
527 
528  //Cold sphere phantoms
529  if(i==0 || i==5){
530  //Surrounding PMMA phantom for the cold sphere
531  //Define the solid shape for the surrounding PMMA phantom for the cold sphere pahntom
532  G4Sphere* coldSpherePMMA = new G4Sphere("coldSphere", 0., sphereDiameter/2 + sphereWallThickness, 0*deg, 360*deg, 0*deg, 180*deg);
533 
534  //Deifne the logical volume of the surrounding PMMA for the cold sphere phantom
535  coldSpherePMMA_logicalV = new G4LogicalVolume(coldSpherePMMA, pmma , "coldRegion_logicalV",0,0,0);
536 
537  //Deifne the physical volume of the surrounding PMMA for the cold sphere phantom
539 
540 
541  //Defining and placing the water in the surrounding PMMA for cold sphere
542  //Define the solid shape of the water phantom for the cold sphere phantom
543  G4Sphere* coldSphereWater = new G4Sphere("coldSphere", 0., sphereDiameter/2, 0*deg, 360*deg, 0*deg, 180*deg);
544 
545  //Define the logical volume of the water phatom for the cold sphere
546  coldSphereWater_logicalV = new G4LogicalVolume(coldSphereWater, water , "coldRegion_logicalV",0,0,0);
547 
548  //Define the physical volume of the water phatom for the cold sphere
550  //G4cout<<"Cold sphere "<<i<<" is placed. "<< " sphereDiameter = " <<sphereDiameter <<" "<< "Position " <<spherePositionX<<" "<< spherePositionY<<" "<<sphereDiameter<<G4endl;
551  //coldSpherePMMA_logicalV->SetVisAttributes (G4VisAttributes::Invisible);
552  //coldSphereWater_logicalV->SetVisAttributes (G4VisAttributes::Invisible);
553  }
554  }
555  }
556 
557  else if(PhantomType == "NEMA_imageQualityPhantom_smallAnimal"){
558  //The follwoing is for NEMA NU-2 image quality phantom for small animal
559  //To see the details of the phantom, please see: http://www.qrm.de/content/pdf/QRM-MicroPET-IQ.pdf
560 
561  //Outside radius of PMMMA
562  phantomRadius = 16.75*mm;// dia=33.5*mm;
563 
564  //Outside length of PMMA
565  phantomLength = 63*mm;
566 
567  //Dimension of water phantom to be filled with activity (hot region).
568  waterPhantomRadius = 15*mm;
569  waterPhantomLength = 30*mm;
570 
571 
572  //Dimension of rod phantom (hot region)
573  rodPhantomLength = 20*mm;
574 
575  //There are five rod phantoms with different diameters
576  numberOfRods = 5;
577 
578  //Distance from the center of the cylinder to the center of the rods
579  distanceFromCenter = 7*mm;
580 
581  //surrounding PMMA phantom.
582  //Define PMMA solid
583  G4Tubs* phantom = new G4Tubs("Phantom", 0*mm,phantomRadius,phantomLength/2,0*deg,360*deg);
584 
585  //Define PMMA logical volume
586  phantom_logicalV = new G4LogicalVolume(phantom, pmma, "phantom_logicalV",0,0,0);
587 
588  //Define PMMA physical volume
589  phantom_physicalV = new G4PVPlacement(0,G4ThreeVector(0,0,0), phantom_logicalV, "pmma_phantom_physicalV", worldLogical, false, 0,fCheckOverlaps);
590 
591  //The rods are placed at one end of the surrounding PMMA cylinderical phantom
593 
594  for(G4int i = 0; i < numberOfRods; i++){
595 
596  if(i == 0) rodDiameter = 1 * mm;
597  if(i == 1) rodDiameter = 2 * mm;
598  if(i == 2) rodDiameter = 3 * mm;
599  if(i == 3) rodDiameter = 4 * mm;
600  if(i == 4) rodDiameter = 5 * mm;
601 
602  rodPositionX = distanceFromCenter*std::cos(((G4double)i*twopi/numberOfRods));
603  rodPositionY = distanceFromCenter*std::sin(((G4double)i*twopi/numberOfRods));
604 
605  //Define rod phantom
606  G4Tubs* rod_phantom = new G4Tubs("Phantom", 0*mm,rodDiameter/2,rodPhantomLength/2,0*deg,360*deg);
607 
608  //Define rod phantom logical volume
609  rod_phantom_logicalV = new G4LogicalVolume(rod_phantom, water, "rod_phantom_logicalV",0,0,0);
610 
611  //Define rod phantom physical volume
613  }
614 
615  //Out dimensions of the surrounding PMMA for cold region chambers
617  chamberDiameter = 10*mm;
618 
619  //Wall thickness of the surrounding PMMA phantom for the cold region chambers
621 
622  //The centers of the cold chambers is
624  chamberPositionY = 0*mm;
626 
627  //hot region filled with water
628  G4Tubs* water_phantom = new G4Tubs("Phantom", 0*mm,waterPhantomRadius,waterPhantomLength/2,0*deg,360*deg);
629 
630  waterPhantom_logicalV = new G4LogicalVolume(water_phantom, water, "waterPhantom_logicalV",0,0,0);
631 
632  //place the phantom at one end of the PMMA phantom
634  //waterPhantom_logicalV->SetVisAttributes (G4VisAttributes::Invisible);
635 
636  //define the surrounding PMMA chamber
637  G4Tubs* chamberPMMA = new G4Tubs("chamber_phantom1", 0*mm,chamberDiameter/2,chamberPhantomLength/2,0*deg,360*deg);
638 
639  //define the logical volume of the surrounding PMMA chamber
640  chamberPMMA_logicalV = new G4LogicalVolume(chamberPMMA, pmma, "chamberPMMA_logicalV",0,0,0);
641 
642  //define the physical volume of the surrounding PMMA chamber
644 
645 
646  //Two cold region chambers: one of them filled with (non-radioactive) water and the other with air and is placed inside a hot region
647  //chamber one filled with water (cold region)
648  //Define the cold region chamber phantom to be filled with water
649  G4Tubs* chamberWater = new G4Tubs("chamber_phantom1", 0*mm,chamberDiameter/2 - wallThicknessOfChamber,chamberPhantomLength/2 - wallThicknessOfChamber,0*deg,360*deg);
650 
651  //Define the logical volume of the cold region phantom
652  chamberWater_logicalV = new G4LogicalVolume(chamberWater, water, "chamber_phantom_logicalV",0,0,0);
653 
654  //Define the physical volume of the cold region phantom
656 
657  //chamber2 filled with air
658  //Place the surrounding chamber at another location (at -chamberPositionX)
660 
661  //Define the logical volume of the cold region phantom to be filled with air
662  G4Tubs* chamberAir = new G4Tubs("chamber_phantom1", 0*mm,chamberDiameter/2 - wallThicknessOfChamber,chamberPhantomLength/2 - wallThicknessOfChamber,0*deg,360*deg);
663 
664  //Define its logical volume
665  chamberAir_logicalV = new G4LogicalVolume(chamberAir, air, "chamber_phantom_logicalV",0,0,0);
666 
667  //Define the physical volume of air-filled chamber
669 
670  }
671 
672  else if(PhantomType == "NEMA_phantom_NECR"){
674  //The phantom is 203 mm in diameter and 700 mm in height and is placed at the center of the AFOV
675 
676  //Define its solid shape
677  G4Tubs* phantom = new G4Tubs("Phantom", 0*mm,phantomRadius,phantomLength/2,0*deg,360*deg);
678 
679  //Define its logical volume
680  phantom_logicalV = new G4LogicalVolume(phantom, polyethylene_NEMA, "phantom_logicalV",0,0,0);
681 
682  //Define its physical volume
683  phantom_physicalV = new G4PVPlacement(0,G4ThreeVector(0,0,0), phantom_logicalV, "phantom_physicalV", worldLogical, false, 0,fCheckOverlaps);
684  }
685  else if(PhantomType == "Phantom_sensitivity"){
686 
688  //There are six diffrent sizes of the sensitivity phantom which differe in their diameter.
689  //The size of the phantom can be changed via the macro file
690  //The hight of sensitivity phantom is 700 mm
691 
692  //Define the solid shape for the sensitivity phantom which surrounds the fillable polyethylene phantom
693  G4Tubs* phantom = new G4Tubs("Phantom_sensitivity", 0 *mm,phantomRadius,phantomLength/2,0*deg,360*deg);
694 
695  //Define its logical volume. The Matrial of the tubes are Aluminum
696  phantom_logicalV = new G4LogicalVolume(phantom, Aluminum, "phantom_logicalV",0,0,0);
697 
698  //Define its physical volume
699  phantom_physicalV = new G4PVPlacement(0, phantomPosition, phantom_logicalV, "phantom_physicalV", worldLogical, false, 0,fCheckOverlaps);
700 
701 
702  //Define the inner most polyethylene (PE) tube with a diameter of 3 mm. This size will not be changed. This is the phantom that holds the source.
703  G4Tubs* phantomPE = new G4Tubs("Phantom_sensitivity", 0 *mm,1.5*mm,phantomLength/2,0*deg,360*deg);
704 
705  //Define its logical volume. The Matrial of the tubes are polyethylene
706  phantomPE_logicalV = new G4LogicalVolume(phantomPE, polyethylene_NEMA, "phantom_logicalV",0,0,0);
707 
708  //Define its physical volume
709  phantomPE_physicalV = new G4PVPlacement(0, G4ThreeVector(0,0,0), phantomPE_logicalV, "phantom_physicalV", phantom_logicalV, false, 0,fCheckOverlaps);
710 
711 
712  G4cout<<"---------------Phantom dimension: "<<"radius (mm) = "<<phantomRadius<<" "<<"Length (mm) = "<<phantomLength<<G4endl;
713  G4cout<<"---------------Phantom position (mm) : "<<phantomPosition<<G4endl;
714  }
715  else if(PhantomType == "Phantom_spatialResolution"){
717  //The position of the point source phantom can be changed in the macro file.
718  //It has cylindrical shape and its radius and length can be set in the macro file
719 
720  //Define its sold shape
721  G4Tubs* phantom = new G4Tubs("Phantom_point", 0., phantomRadius,phantomLength/2,0*deg,360*deg);
722 
723  //Define its logical volume
724  phantom_logicalV = new G4LogicalVolume(phantom, polyethylene_NEMA , "phantom_logicalV",0,0,0);
725 
726  //place the phantom
728 
729  //Define its physical volume
730  phantom_physicalV = new G4PVPlacement(0, phantomPosition, phantom_logicalV, "phantom_physicalV", worldLogical, false, 0,fCheckOverlaps);
731  G4cout<<"---------------Phantom dimension: "<<"radius (mm) = "<<phantomRadius<<" "<<", Length (mm) = "<<phantomLength<<G4endl;
732  G4cout<<"---------------Phantom position: "<<phantomPosition<< "mm"<<G4endl;
733  }
734 
735  else if (PhantomType == "Normalization")
736  {
737  //The normalization phantom is a hallow cylindrical phantom to represent a (rotating) line source. The source is confined in the phantom.
738  //The thickness of the phantom is 3 mm, and its diameter is 350 mm.
739 
740  //Define the solid shape.
741  G4Tubs* phantom = new G4Tubs("Phantom", phantomRadius - 3*mm, phantomRadius,phantomLength/2,0*deg,360*deg);
742 
743  //Define its logical volume.
744  phantom_logicalV = new G4LogicalVolume(phantom, polyethylene_NEMA, "phantom_logicalV",0,0,0);
745 
746  //Define its physical volume
747  phantom_physicalV = new G4PVPlacement(0, phantomPosition, phantom_logicalV, "phantom_physicalV", worldLogical, false, 0,fCheckOverlaps);
748 
749 
750  G4cout<<"---------------Phantom dimension: "<<"radius (mm) = "<<phantomRadius<<" "<<"Length = "<<phantomLength<<G4endl;
751  G4cout<<"---------------Phantom position : "<<phantomPosition<< "mm"<<G4endl;
752 
753  }
754  //-------------------------------------================- No Phantom Set -==================------------------
755  else
756  {
757  G4cerr << "****************************************\nERROR: Phantom Remains: " << PhantomType <<"\n****************************************" << G4endl;
758  exit(0);
759 
760  }
762 
763  G4VisAttributes* phantomVisAtt;
764  phantomVisAtt = new G4VisAttributes(G4Colour(0.88,0.55,1.0));
765  phantomVisAtt->SetVisibility (true);
766  phantomVisAtt->SetForceWireframe (true);
767  phantom_logicalV->SetVisAttributes (phantomVisAtt);
768  //phantom_logicalV->SetVisAttributes (G4VisAttributes::Invisible);
769 }
770 
771 //Change the type of the phantom via .mac file
773 {
774  PhantomType = NewPhantomtype;
775 }
776 
777 //Change position of the phantom via .mac file
779 {
780  phantomPosition = NewphantomPosition;
781 }
782 
783 //Change the radius of the phantom via .mac file
785  phantomRadius = newPhantomRadius;
786 }
787 
788 //Change the length of the phantom via .mac file
790  phantomLength = newPhantomLength;
791 }
792 
793 
794