Geant4 Cross Reference |
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 27 #include "G4SDManager.hh" 28 #include "G4RunManager.hh" 29 #include "G4Box.hh" 30 #include "G4Tubs.hh" 31 #include "G4Cons.hh" 32 #include "G4Orb.hh" 33 #include "G4LogicalVolume.hh" 34 #include "G4ThreeVector.hh" 35 #include "G4PVPlacement.hh" 36 #include "globals.hh" 37 #include "G4RotationMatrix.hh" 38 #include "G4Colour.hh" 39 #include "G4UserLimits.hh" 40 #include "G4VisAttributes.hh" 41 #include "G4NistManager.hh" 42 43 #include "GammaKnifeDetectorMessenger.hh" 44 #include "GammaKnifeDetectorConstruction.hh" 45 46 #include "G4SystemOfUnits.hh" 47 48 GammaKnifeDetectorConstruction::GammaKnifeDetectorConstruction() 49 : physicalTreatmentRoom(0), 50 patientPhysicalVolume(0), 51 patientLogicalVolume(0), 52 solidColl_helmet(0), 53 helmetSize(4) 54 { 55 // Messenger to change parameters of the geometry 56 detectorMessenger = new GammaKnifeDetectorMessenger(this); 57 } 58 59 GammaKnifeDetectorConstruction::~GammaKnifeDetectorConstruction() 60 { 61 delete detectorMessenger; 62 } 63 64 G4VPhysicalVolume* GammaKnifeDetectorConstruction::Construct() 65 { 66 // Define the geometry components 67 ConstructBeamLine(); 68 69 return physicalTreatmentRoom; 70 } 71 72 void GammaKnifeDetectorConstruction::ConstructBeamLine() 73 { 74 // NIST Materials 75 G4Material* air = G4NistManager::Instance()->FindOrBuildMaterial("G4_AIR"); 76 G4Material* water = G4NistManager::Instance()->FindOrBuildMaterial("G4_WATER"); 77 G4Material* cobalt = G4NistManager::Instance()->FindOrBuildMaterial("G4_Co"); 78 G4Material* Pb = G4NistManager::Instance()->FindOrBuildMaterial("G4_Pb"); 79 G4Material* tungsten = G4NistManager::Instance()->FindOrBuildMaterial("G4_W"); 80 G4Material* Al = G4NistManager::Instance()->FindOrBuildMaterial("G4_Al"); 81 G4Material* Fe = G4NistManager::Instance()->FindOrBuildMaterial("G4_Fe"); 82 83 // Steel as non-NIST material 84 G4Element* elFe = G4NistManager::Instance()->FindOrBuildElement("Fe"); 85 G4Element* elNi = G4NistManager::Instance()->FindOrBuildElement("Ni"); 86 G4Element* elCr = G4NistManager::Instance()->FindOrBuildElement("Cr"); 87 G4Material* steel = new G4Material("StainlessSteel", 7.80 * g/cm3, 3 /* components */); 88 steel -> AddElement(elFe, 70 * perCent); 89 steel -> AddElement(elCr, 18 * perCent); 90 steel -> AddElement(elNi, 12 * perCent); 91 92 // ----------------------------- 93 // Treatment room - World volume 94 // ----------------------------- 95 96 // Treatment room sizes 97 const G4double worldX = 400.0 *cm; 98 const G4double worldY = 400.0 *cm; 99 const G4double worldZ = 400.0 *cm; 100 101 G4Box* treatmentRoom = new G4Box("TreatmentRoom",worldX,worldY,worldZ); 102 103 G4LogicalVolume* logicTreatmentRoom = new G4LogicalVolume(treatmentRoom, 104 air, 105 "logicTreatmentRoom", 106 0,0,0); 107 108 physicalTreatmentRoom = new G4PVPlacement(0, 109 G4ThreeVector(), 110 "physicalTreatmentRoom", 111 logicTreatmentRoom, 112 0,false,0); 113 114 115 // The treatment room is invisible in the Visualisation 116 logicTreatmentRoom -> SetVisAttributes (G4VisAttributes::GetInvisible()); 117 118 119 // Visualisation attributes of all elements colours 120 G4VisAttributes * grayFe = new G4VisAttributes(G4Colour(0.5 ,0.5 ,0.5)); 121 grayFe -> SetVisibility(true); 122 grayFe -> SetForceSolid(true); 123 124 G4VisAttributes * blueCobalt = new G4VisAttributes(G4Colour(0. ,0. ,0.7)); 125 blueCobalt -> SetVisibility(true); 126 blueCobalt -> SetForceSolid(true); 127 128 G4VisAttributes * graySS = new G4VisAttributes(G4Colour(0.9 ,0.9 ,0.9)); 129 graySS -> SetVisibility(true); 130 graySS -> SetForceSolid(true); 131 132 G4VisAttributes * grayAl = new G4VisAttributes(G4Colour(0.7 ,0.7 ,0.7)); 133 grayAl -> SetVisibility(true); 134 grayAl -> SetForceSolid(true); 135 136 G4VisAttributes * blackLead = new G4VisAttributes(G4Colour(0.2 ,0.2 ,0.2)); 137 blackLead -> SetVisibility(true); 138 blackLead -> SetForceSolid(true); 139 140 141 G4VisAttributes * colorTungsten = new G4VisAttributes(G4Colour(0.3 ,0.3 ,0.3)); 142 colorTungsten -> SetVisibility(true); 143 colorTungsten -> SetForceSolid(true); 144 145 146 147 148 149 //-------------------------------------------- 150 // Cylinder source "Tube_source" 151 //-------------------------------------------- 152 G4double innerRadiusOfTheTube_source = 0.; 153 G4double outerRadiusOfTheTube_source = 0.5*mm; 154 G4double hightOfTheTube_source = 1*cm; 155 G4double startAngleOfTheTube = 0.*deg; 156 G4double spanningAngleOfTheTube = 360.*deg; 157 158 G4ThreeVector positionTube_source = G4ThreeVector(0,0,-40.1*cm); 159 160 solidTube_source = new G4Tubs("solidTube_source", 161 innerRadiusOfTheTube_source, 162 outerRadiusOfTheTube_source, 163 hightOfTheTube_source, 164 startAngleOfTheTube, 165 spanningAngleOfTheTube); 166 logicTube_source = new G4LogicalVolume(solidTube_source,cobalt,"logicTube_source",0,0,0); 167 physiTube_source = new G4PVPlacement(0, 168 positionTube_source, 169 logicTube_source, 170 "Tube_source", 171 logicTreatmentRoom, 172 false, 173 0); 174 175 logicTube_source -> SetVisAttributes(blueCobalt); 176 177 178 //------------------------------------- 179 // Cylinder covering source "Tube" 180 //------------------------------------- 181 G4double innerRadiusOfTheTube = 0.5*mm; 182 G4double outerRadiusOfTheTube = 4.*mm; 183 G4double hightOfTheTube = 1*cm; 184 185 186 G4ThreeVector positionTube = G4ThreeVector(0,0,-40.1*cm); 187 188 solidTube = new G4Tubs("solidTube", 189 innerRadiusOfTheTube, 190 outerRadiusOfTheTube, 191 hightOfTheTube, 192 startAngleOfTheTube, 193 spanningAngleOfTheTube); 194 logicTube = new G4LogicalVolume(solidTube,steel,"logicTube",0,0,0); 195 physiTube = new G4PVPlacement(0, 196 positionTube, 197 logicTube, 198 "Tube", 199 logicTreatmentRoom, 200 false, 201 0); 202 203 logicTube -> SetVisAttributes(graySS); 204 205 //--------------------------------------- 206 // Cylinder covering source "Tube_Al" 207 //--------------------------------------- 208 G4double innerRadiusOfTheTube_Al = 4.*mm; 209 G4double outerRadiusOfTheTube_Al = 15.*mm; 210 G4double hightOfTheTube_Al = 1*cm; 211 212 G4ThreeVector positionTube_Al = G4ThreeVector(0,0,-40.1*cm); 213 214 solidTube_Al = new G4Tubs("solidTube_Al", 215 innerRadiusOfTheTube_Al, 216 outerRadiusOfTheTube_Al, 217 hightOfTheTube_Al, 218 startAngleOfTheTube, 219 spanningAngleOfTheTube); 220 logicTube_Al = new G4LogicalVolume(solidTube_Al,Al,"logicTube_Al",0,0,0); 221 physiTube_Al = new G4PVPlacement(0, 222 positionTube_Al, 223 logicTube_Al, 224 "Tube_Al", 225 logicTreatmentRoom, 226 false, 227 0); 228 229 logicTube_Al -> SetVisAttributes(grayAl); 230 231 //---------------------------------------------- 232 // Cylinder covering external part of the source "Tube_Fe" 233 //---------------------------------------------- 234 G4double innerRadiusOfTheTube_Fe = 15.*mm; 235 G4double outerRadiusOfTheTube_Fe = 50.*mm; 236 G4double hightOfTheTube_Fe = 1*cm; 237 238 239 G4ThreeVector positionTube_Fe = G4ThreeVector(0,0,-40.1*cm); 240 241 solidTube_Fe = new G4Tubs("solidTube_Fe", 242 innerRadiusOfTheTube_Fe, 243 outerRadiusOfTheTube_Fe, 244 hightOfTheTube_Fe, 245 startAngleOfTheTube, 246 spanningAngleOfTheTube); 247 logicTube_Fe = new G4LogicalVolume(solidTube_Fe,Fe,"logicTube_Fe",0,0,0); 248 physiTube_Fe = new G4PVPlacement(0, 249 positionTube_Fe, 250 logicTube_Fe, 251 "Tube_Fe", 252 logicTreatmentRoom, 253 false, 254 0); 255 256 logicTube_Fe -> SetVisAttributes(grayFe); 257 258 259 260 261 //------------------------------------------------ 262 // Cylinder covering posterior part "Tube_post" 263 //------------------------------------------------ 264 265 G4double innerRadiusOfTheTube_post = 0; 266 G4double outerRadiusOfTheTube_post = 50*mm; 267 G4double hightOfTheTube_post = 1*cm; 268 269 G4ThreeVector positionTube_post = G4ThreeVector(0,0,-42.2*cm); 270 271 solidTube_post = new G4Tubs("solidTube_post", 272 innerRadiusOfTheTube_post, 273 outerRadiusOfTheTube_post, 274 hightOfTheTube_post, 275 startAngleOfTheTube, 276 spanningAngleOfTheTube); 277 logicTube_post = new G4LogicalVolume(solidTube_post,Fe,"logicTube_post",0,0,0); 278 physiTube_post = new G4PVPlacement(0, 279 positionTube_post, 280 logicTube_post, 281 "Tube_post", 282 logicTreatmentRoom, 283 false, 284 0); 285 286 logicTube_post -> SetVisAttributes(grayFe); 287 288 289 //------------------------------------------------ 290 // Fixed cylinder collimator "Tube_coll" 291 //------------------------------------------------ 292 293 G4double innerRadiusOfTheTube_coll = 2.5*mm; 294 G4double outerRadiusOfTheTube_coll = 15.*mm; 295 G4double hightOfTheTube_coll = 3.25*cm; 296 297 G4ThreeVector positionTube_coll = G4ThreeVector(0,0,-35.2*cm); 298 299 solidTube_coll = new G4Tubs("solidTube_coll", 300 innerRadiusOfTheTube_coll, 301 outerRadiusOfTheTube_coll, 302 hightOfTheTube_coll, 303 startAngleOfTheTube, 304 spanningAngleOfTheTube); 305 logicTube_coll = new G4LogicalVolume(solidTube_coll,tungsten,"logicTube_coll",0,0,0); 306 physiTube_coll = new G4PVPlacement(0, 307 positionTube_coll, 308 logicTube_coll, 309 "Tube_coll", 310 logicTreatmentRoom, 311 false, 312 0); 313 314 logicTube_coll -> SetVisAttributes(colorTungsten); 315 316 317 //------------------------------------------------ 318 // Cylinder covering fixed collimator "Tube_coll_Fe" 319 //------------------------------------------------ 320 321 G4double innerRadiusOfTheTube_coll_Fe = 15.*mm; 322 G4double outerRadiusOfTheTube_coll_Fe = 50.*mm; 323 G4double hightOfTheTube_coll_Fe = 3.25*cm; 324 325 G4ThreeVector positionTube_coll_Fe = G4ThreeVector(0,0,-35.2*cm); 326 327 solidTube_coll_Fe = new G4Tubs("solidTube_coll_Fe", 328 innerRadiusOfTheTube_coll_Fe, 329 outerRadiusOfTheTube_coll_Fe, 330 hightOfTheTube_coll_Fe, 331 startAngleOfTheTube, 332 spanningAngleOfTheTube); 333 logicTube_coll_Fe = new G4LogicalVolume(solidTube_coll_Fe,Fe,"logicTube_coll_Fe",0,0,0); 334 physiTube_coll_Fe = new G4PVPlacement(0, 335 positionTube_coll_Fe, 336 logicTube_coll_Fe, 337 "Tube_coll_Fe", 338 logicTreatmentRoom, 339 false, 340 0); 341 342 logicTube_coll_Fe -> SetVisAttributes(grayFe); 343 344 345 //------------------------------------------------ 346 // Fixed truncated cone collimator "Coll_fixed" 347 //------------------------------------------------ 348 349 G4double Rmin1Coll_fixed = 2.5*mm; 350 G4double Rmax1Coll_fixed = 15.*mm; 351 G4double Rmin2Coll_fixed = 4.25*mm; 352 G4double Rmax2Coll_fixed = 15.*mm; 353 G4double hightColl_fixed = 4.625*cm; 354 355 356 G4ThreeVector positionColl_fixed = G4ThreeVector(0,0,-27.325*cm); 357 358 solidColl_fixed = new G4Cons("solidColl_fixed", 359 Rmin1Coll_fixed, 360 Rmax1Coll_fixed, 361 Rmin2Coll_fixed, 362 Rmax2Coll_fixed, 363 hightColl_fixed, 364 startAngleOfTheTube, 365 spanningAngleOfTheTube); 366 logicColl_fixed = new G4LogicalVolume(solidColl_fixed,Pb,"logicColl_fixed",0,0,0); 367 physiColl_fixed = new G4PVPlacement(0, 368 positionColl_fixed, 369 logicColl_fixed, 370 "Coll_fixed", 371 logicTreatmentRoom, 372 false, 373 0); 374 375 logicColl_fixed -> SetVisAttributes(blackLead); 376 377 378 //----------------------------------------------------------- 379 // Cilinder covering fixed collimator "Coll_fixed_Fe" 380 //----------------------------------------------------------- 381 382 G4double Rmin1Coll_fixed_Fe = 15.*mm; 383 G4double Rmax1Coll_fixed_Fe = 50.*mm; 384 G4double Rmin2Coll_fixed_Fe = 15.*mm; 385 G4double Rmax2Coll_fixed_Fe = 40.*mm; 386 G4double hightColl_fixed_Fe = 4.625*cm; 387 388 389 G4ThreeVector positionColl_fixed_Fe = G4ThreeVector(0,0,-27.325*cm); 390 391 solidColl_fixed_Fe = new G4Cons("solidColl_fixed_Fe", 392 Rmin1Coll_fixed_Fe, 393 Rmax1Coll_fixed_Fe, 394 Rmin2Coll_fixed_Fe, 395 Rmax2Coll_fixed_Fe, 396 hightColl_fixed_Fe, 397 startAngleOfTheTube, // 398 spanningAngleOfTheTube); 399 logicColl_fixed_Fe = new G4LogicalVolume(solidColl_fixed_Fe,Fe,"logicColl_fixed_Fe",0,0,0); 400 physiColl_fixed_Fe = new G4PVPlacement(0, 401 positionColl_fixed_Fe, 402 logicColl_fixed_Fe, 403 "Coll_fixed_Fe", 404 logicTreatmentRoom, 405 false, 406 0); 407 408 logicColl_fixed_Fe -> SetVisAttributes(grayFe); 409 410 411 //------------------------------------------------ 412 // Mobile truncate cone collimator "Coll_helmet" 413 //------------------------------------------------ 414 G4double Rmax1Coll_helmet = 15.*mm; 415 G4double Rmax2Coll_helmet = 15.*mm; 416 G4double hightColl_helmet = 3.0*cm; 417 418 419 G4ThreeVector positionColl_helmet = G4ThreeVector(0,0,-19.5*cm); 420 421 solidColl_helmet = new G4Cons("solidColl_helmet", 422 0.0, // will be set later 423 Rmax1Coll_helmet, 424 0.0, // will be set later 425 Rmax2Coll_helmet, 426 hightColl_helmet, 427 startAngleOfTheTube, 428 spanningAngleOfTheTube); 429 UpdateHelmet(); // Set the proper inner radii 430 431 logicColl_helmet = new G4LogicalVolume(solidColl_helmet,tungsten,"logicColl_helmet",0,0,0); 432 physiColl_helmet = new G4PVPlacement(0, 433 positionColl_helmet, 434 logicColl_helmet, 435 "Coll_helmet", 436 logicTreatmentRoom, 437 false, 438 0); 439 440 logicColl_helmet -> SetVisAttributes(colorTungsten); 441 442 //-------------------------------------------------------------- 443 // Truncated cone covering mobile collimator "Coll_helmet_Fe" 444 //-------------------------------------------------------------- 445 446 G4double Rmin1Coll_helmet_Fe = 15.*mm; 447 G4double Rmax1Coll_helmet_Fe = 40.*mm; 448 G4double Rmin2Coll_helmet_Fe = 15.*mm; 449 G4double Rmax2Coll_helmet_Fe = 30.*mm; 450 G4double hightColl_helmet_Fe = 3.0*cm; 451 452 G4ThreeVector positionColl_helmet_Fe = G4ThreeVector(0,0,-19.5*cm); 453 454 solidColl_helmet_Fe = new G4Cons("solidColl_helmet_Fe", 455 Rmin1Coll_helmet_Fe, 456 Rmax1Coll_helmet_Fe, 457 Rmin2Coll_helmet_Fe, 458 Rmax2Coll_helmet_Fe, 459 hightColl_helmet_Fe, 460 startAngleOfTheTube, 461 spanningAngleOfTheTube); 462 logicColl_helmet_Fe = new G4LogicalVolume(solidColl_helmet_Fe,Fe,"logicColl_helmet_Fe",0,0,0); 463 physiColl_helmet_Fe = new G4PVPlacement(0, 464 positionColl_helmet_Fe, 465 logicColl_helmet_Fe, 466 "Coll_helmet_Fe", 467 logicTreatmentRoom, 468 false, 469 0); 470 471 logicColl_helmet_Fe -> SetVisAttributes(grayFe); 472 473 //----------------------------------------- 474 // Patient --> water spherical phantom 475 //----------------------------------------- 476 477 478 G4Orb* patient = new G4Orb("patient",8.*cm); 479 patientLogicalVolume = new G4LogicalVolume(patient, 480 water, 481 "patientLog", 0, 0, 0); 482 patientPhysicalVolume = new G4PVPlacement( new G4RotationMatrix(), 483 G4ThreeVector(0., 0., 0.), 484 "patientPhys", 485 patientLogicalVolume, 486 physicalTreatmentRoom, 487 false,0); 488 489 // Visualisation attributes of the patient 490 G4VisAttributes * redWire = new G4VisAttributes(G4Colour(0.8 ,0. ,0.)); 491 redWire -> SetVisibility(true); 492 redWire -> SetForceWireframe(true); 493 redWire -> SetForceAuxEdgeVisible(true); 494 patientLogicalVolume -> SetVisAttributes(redWire); 495 496 } 497 498 void GammaKnifeDetectorConstruction::UpdateHelmet() 499 { 500 if (solidColl_helmet) 501 { 502 switch( helmetSize ) 503 { 504 case 18: 505 solidColl_helmet->SetInnerRadiusMinusZ( 4.15 * mm ); 506 solidColl_helmet->SetInnerRadiusPlusZ( 5.3 * mm ); 507 break; 508 509 case 14: 510 solidColl_helmet->SetInnerRadiusMinusZ( 3.15 * mm ); 511 solidColl_helmet->SetInnerRadiusPlusZ( 4.25 * mm ); 512 break; 513 514 case 8: 515 solidColl_helmet->SetInnerRadiusMinusZ( 1.9 * mm ); 516 solidColl_helmet->SetInnerRadiusPlusZ( 2.5 * mm ); 517 break; 518 519 case 4: 520 solidColl_helmet->SetInnerRadiusMinusZ( 1. * mm ); 521 solidColl_helmet->SetInnerRadiusPlusZ( 1.25 * mm ); 522 break; 523 } 524 // Inform the run manager about change in the geometry 525 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 526 } 527 } 528 529 void GammaKnifeDetectorConstruction::SetHelmetSize(G4int size) 530 { 531 if (size != helmetSize) // Only if the size changes 532 { 533 // Allow only valid numbers 534 switch( size ) 535 { 536 case 18: 537 case 14: 538 case 8: 539 case 4: 540 helmetSize = size; 541 G4cout << "Helmet size set to " << helmetSize << std::endl; 542 UpdateHelmet(); 543 break; 544 default: 545 G4Exception("GammaKnifeDetectorConstruction::SetHelmetSize()", 546 "GammaKnife001", FatalException, 547 "Error: Invalid helmet size."); 548 return; 549 } 550 } 551 } 552 553 554 555