Import Geant4 9.1.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-09 15:37:50 +02:00
parent a8e9364cea
commit 96c8bcd0af
6923 changed files with 198390 additions and 41849 deletions
@@ -1,149 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// The code was written by :
// *Louis Archambault louis.archambault@phy.ulaval.ca,
// *Luc Beaulieu beaulieu@phy.ulaval.ca
// +Vincent Hubert-Tremblay at tigre.2@sympatico.ca
//
//
// *Centre Hospitalier Universitaire de Quebec (CHUQ),
// Hotel-Dieu de Quebec, departement de Radio-oncologie
// 11 cote du palais. Quebec, QC, Canada, G1R 2J6
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Université Laval, Québec (QC) Canada
//*******************************************************
//
//
// DicomConfiguration.cc :
// - Handling of the header of *.g4 files
// - Reading <Data.dat> file
#include "globals.hh"
#include "DicomConfiguration.hh"
#include <fstream>
#include <vector>
short DicomConfiguration::compressionValue = 0;
G4int DicomConfiguration::totalNumberOfFile = 0;
std::vector<G4String> DicomConfiguration::listOfFile;
short DicomConfiguration::totalRows = 0;
short DicomConfiguration::totalColumns = 0;
G4int DicomConfiguration::totalPixels = 0;
G4double DicomConfiguration::xPixelSpacing = 0.;
G4double DicomConfiguration::yPixelSpacing = 0.;
G4double DicomConfiguration::sliceTickness = 0.;
std::vector<G4double> DicomConfiguration::sliceLocation;
short DicomConfiguration::compressionUsed = 0;
std::vector<G4double> DicomConfiguration::densityValue;
//
DicomConfiguration::DicomConfiguration() {
ReadDataFile();
}
//
G4bool DicomConfiguration::ReadDataFile() {
if(totalNumberOfFile > 0) return true;
totalPixels = 0;
std::ifstream dataFile("Data.dat");
G4String nameOfFileBuffer;
if(dataFile.good() != 1 ) return 1;
dataFile >> compressionValue;
dataFile >> totalNumberOfFile;
for(G4int i = 0; i < totalNumberOfFile; i++ ) {
dataFile >> nameOfFileBuffer;
listOfFile.push_back( nameOfFileBuffer );
// read densities from .g4 file
ReadG4File(nameOfFileBuffer);
}
dataFile.close();
return 0;
}
G4int DicomConfiguration::ReadG4File( G4String g4File ) {
//densityValue.clear();
g4File = g4File + ".g4";
std::ifstream readingG4FileHeader(g4File.c_str(),
std::ios_base::in | std::ios_base::binary);
if ( readingG4FileHeader.good() != 1 ) return 1;
readingG4FileHeader.read((char *)&totalRows, 2);
readingG4FileHeader.read((char *)&totalColumns, 2);
readingG4FileHeader.read((char *)&xPixelSpacing, 8);
readingG4FileHeader.read((char *)&yPixelSpacing, 8);
readingG4FileHeader.read((char *)&sliceTickness, 8);
G4double sliceLocationBuff;
readingG4FileHeader.read((char *)&sliceLocationBuff, 8);
readingG4FileHeader.read((char *)&compressionUsed, 2);
sliceLocation.push_back(sliceLocationBuff);
G4double density;
for(int y = 0; y < totalRows/compressionUsed; y++) {
for(int x = 0; x < totalColumns/compressionUsed; x++) {
readingG4FileHeader.read((char *)&density, sizeof(G4double));
densityValue.push_back(density);
totalPixels++;
}
}
readingG4FileHeader.close();
return 0;
}
G4double DicomConfiguration::GetDensityValue(G4int i) {
G4double value = 0.;
if (i >= 0) {
unsigned int j = i;
//
if(j > densityValue.size() ) {
// Throw exception, return dummy, cerr error message...
G4cout << "out of range in GetDensityValue()! : "
<< j << ", " << totalPixels << G4endl;
} else {
value = densityValue[i];
}
} else {
G4cout << "out of range in GetDensityValue()!"<<G4endl;
}
return value;
}
@@ -0,0 +1,452 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
#include "globals.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4VPhysicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "DicomDetectorConstruction.hh"
#include "DicomPatientZSliceHeader.hh"
//-------------------------------------------------------------
DicomDetectorConstruction::DicomDetectorConstruction()
{
}
//-------------------------------------------------------------
DicomDetectorConstruction::~DicomDetectorConstruction()
{
}
//-------------------------------------------------------------
G4VPhysicalVolume* DicomDetectorConstruction::Construct()
{
InitialisationOfMaterials();
//----- Build world
G4double worldXDimension = 1.*m;
G4double worldYDimension = 1.*m;
G4double worldZDimension = 1.*m;
world_solid = new G4Box( "WorldSolid",
worldXDimension,
worldYDimension,
worldZDimension );
world_logic = new G4LogicalVolume( world_solid,
air,
"WorldLogical",
0, 0, 0 );
world_phys = new G4PVPlacement( 0,
G4ThreeVector(0,0,0),
"World",
world_logic,
0,
false,
0 );
ReadPatientData();
ConstructPatientContainer();
ConstructPatient();
return world_phys;
}
//-------------------------------------------------------------
void DicomDetectorConstruction::InitialisationOfMaterials()
{
// Creating elements :
G4double z, a, density;
G4String name, symbol;
G4Element* elC = new G4Element( name = "Carbon",
symbol = "C",
z = 6.0, a = 12.011 * g/mole );
G4Element* elH = new G4Element( name = "Hydrogen",
symbol = "H",
z = 1.0, a = 1.008 * g/mole );
G4Element* elN = new G4Element( name = "Nitrogen",
symbol = "N",
z = 7.0, a = 14.007 * g/mole );
G4Element* elO = new G4Element( name = "Oxygen",
symbol = "O",
z = 8.0, a = 16.00 * g/mole );
G4Element* elNa = new G4Element( name = "Sodium",
symbol = "Na",
z= 11.0, a = 22.98977* g/mole );
G4Element* elS = new G4Element( name = "Sulfur",
symbol = "S",
z = 16.0,a = 32.065* g/mole );
G4Element* elCl = new G4Element( name = "Chlorine",
symbol = "P",
z = 17.0, a = 35.453* g/mole );
G4Element* elK = new G4Element( name = "Potassium",
symbol = "P",
z = 19.0, a = 30.0983* g/mole );
G4Element* elP = new G4Element( name = "Phosphorus",
symbol = "P",
z = 30.0, a = 30.973976* g/mole );
G4Element* elFe = new G4Element( name = "Iron",
symbol = "Fe",
z = 26, a = 56.845* g/mole );
G4Element* elMg = new G4Element( name = "Magnesium",
symbol = "Mg",
z = 12.0, a = 24.3050* g/mole );
G4Element* elCa = new G4Element( name="Calcium",
symbol = "Ca",
z = 20.0, a = 40.078* g/mole );
// Creating Materials :
G4int numberofElements;
// Air
air = new G4Material( "Air",
1.290*mg/cm3,
numberofElements = 2 );
air->AddElement(elN, 0.7);
air->AddElement(elO, 0.3);
// Lung Inhale
G4Material* lunginhale = new G4Material( "LungInhale",
density = 0.217*g/cm3,
numberofElements = 9);
lunginhale->AddElement(elH,0.103);
lunginhale->AddElement(elC,0.105);
lunginhale->AddElement(elN,0.031);
lunginhale->AddElement(elO,0.749);
lunginhale->AddElement(elNa,0.002);
lunginhale->AddElement(elP,0.002);
lunginhale->AddElement(elS,0.003);
lunginhale->AddElement(elCl,0.002);
lunginhale->AddElement(elK,0.003);
// Lung exhale
G4Material* lungexhale = new G4Material( "LungExhale",
density = 0.508*g/cm3,
numberofElements = 9 );
lungexhale->AddElement(elH,0.103);
lungexhale->AddElement(elC,0.105);
lungexhale->AddElement(elN,0.031);
lungexhale->AddElement(elO,0.749);
lungexhale->AddElement(elNa,0.002);
lungexhale->AddElement(elP,0.002);
lungexhale->AddElement(elS,0.003);
lungexhale->AddElement(elCl,0.002);
lungexhale->AddElement(elK,0.003);
// Adipose tissue
G4Material* adiposeTissue = new G4Material( "AdiposeTissue",
density = 0.967*g/cm3,
numberofElements = 7);
adiposeTissue->AddElement(elH,0.114);
adiposeTissue->AddElement(elC,0.598);
adiposeTissue->AddElement(elN,0.007);
adiposeTissue->AddElement(elO,0.278);
adiposeTissue->AddElement(elNa,0.001);
adiposeTissue->AddElement(elS,0.001);
adiposeTissue->AddElement(elCl,0.001);
// Breast
G4Material* breast = new G4Material( "Breast",
density = 0.990*g/cm3,
numberofElements = 8 );
breast->AddElement(elH,0.109);
breast->AddElement(elC,0.506);
breast->AddElement(elN,0.023);
breast->AddElement(elO,0.358);
breast->AddElement(elNa,0.001);
breast->AddElement(elP,0.001);
breast->AddElement(elS,0.001);
breast->AddElement(elCl,0.001);
// Water
G4Material* water = new G4Material( "Water",
density = 1.0*g/cm3,
numberofElements = 2 );
water->AddElement(elH,0.112);
water->AddElement(elO,0.888);
// Muscle
G4Material* muscle = new G4Material( "Muscle",
density = 1.061*g/cm3,
numberofElements = 9 );
muscle->AddElement(elH,0.102);
muscle->AddElement(elC,0.143);
muscle->AddElement(elN,0.034);
muscle->AddElement(elO,0.710);
muscle->AddElement(elNa,0.001);
muscle->AddElement(elP,0.002);
muscle->AddElement(elS,0.003);
muscle->AddElement(elCl,0.001);
muscle->AddElement(elK,0.004);
// Liver
G4Material* liver = new G4Material( "Liver",
density = 1.071*g/cm3,
numberofElements = 9);
liver->AddElement(elH,0.102);
liver->AddElement(elC,0.139);
liver->AddElement(elN,0.030);
liver->AddElement(elO,0.716);
liver->AddElement(elNa,0.002);
liver->AddElement(elP,0.003);
liver->AddElement(elS,0.003);
liver->AddElement(elCl,0.002);
liver->AddElement(elK,0.003);
// Trabecular Bone
G4Material* trabecularBone = new G4Material( "TrabecularBone",
density = 1.159*g/cm3,
numberofElements = 12 );
trabecularBone->AddElement(elH,0.085);
trabecularBone->AddElement(elC,0.404);
trabecularBone->AddElement(elN,0.058);
trabecularBone->AddElement(elO,0.367);
trabecularBone->AddElement(elNa,0.001);
trabecularBone->AddElement(elMg,0.001);
trabecularBone->AddElement(elP,0.034);
trabecularBone->AddElement(elS,0.002);
trabecularBone->AddElement(elCl,0.002);
trabecularBone->AddElement(elK,0.001);
trabecularBone->AddElement(elCa,0.044);
trabecularBone->AddElement(elFe,0.001);
// Dense Bone
G4Material* denseBone = new G4Material( "DenseBone",
density = 1.575*g/cm3,
numberofElements = 11 );
denseBone->AddElement(elH,0.056);
denseBone->AddElement(elC,0.235);
denseBone->AddElement(elN,0.050);
denseBone->AddElement(elO,0.434);
denseBone->AddElement(elNa,0.001);
denseBone->AddElement(elMg,0.001);
denseBone->AddElement(elP,0.072);
denseBone->AddElement(elS,0.003);
denseBone->AddElement(elCl,0.001);
denseBone->AddElement(elK,0.001);
denseBone->AddElement(elCa,0.146);
//----- Put the materials in a vector
fOriginalMaterials.push_back(air); // rho = 0.00129
fOriginalMaterials.push_back(lunginhale); // rho = 0.217
fOriginalMaterials.push_back(lungexhale); // rho = 0.508
fOriginalMaterials.push_back(adiposeTissue); // rho = 0.967
fOriginalMaterials.push_back(breast ); // rho = 0.990
fOriginalMaterials.push_back(water); // rho = 1.018
fOriginalMaterials.push_back(muscle); // rho = 1.061
fOriginalMaterials.push_back(liver); // rho = 1.071
fOriginalMaterials.push_back(trabecularBone); // rho = 1.159
fOriginalMaterials.push_back(denseBone); // rho = 1.575
}
//-------------------------------------------------------------
void DicomDetectorConstruction::ReadPatientData()
{
std::ifstream finDF("Data.dat");
G4String fname;
if(finDF.good() != 1 ) {
G4Exception(" DicomDetectorConstruction::ReadPatientData. Problem reading data file: Data.dat");
}
G4int compression;
finDF >> compression; // not used here
finDF >> fNoFiles;
for(G4int i = 0; i < fNoFiles; i++ ) {
finDF >> fname;
//--- Read one data file
fname += ".g4dcm";
ReadPatientDataFile(fname);
}
//----- Merge data headers
MergeZSliceHeaders();
finDF.close();
}
//-------------------------------------------------------------
void DicomDetectorConstruction::ReadPatientDataFile(const G4String& fname)
{
#ifdef G4VERBOSE
G4cout << " DicomDetectorConstruction::ReadPatientDataFile opening file " << fname << G4endl;
#endif
std::ifstream fin(fname.c_str(), std::ios_base::in);
if( !fin.is_open() ) {
G4Exception("DicomDetectorConstruction::ReadPatientDataFil. File not found " + fname );
}
//----- Define density differences (maximum density difference to create a new material)
G4double densityDiff = 0.1;
std::map<G4int,G4double> fDensityDiffs; // to be able to use a different densityDiff for each material
for( size_t ii = 0; ii < fOriginalMaterials.size(); ii++ ){
fDensityDiffs[ii] = densityDiff; //currently all materials with same difference
}
//----- Read data header
DicomPatientZSliceHeader* sliceHeader = new DicomPatientZSliceHeader( fin );
fZSliceHeaders.push_back( sliceHeader );
//----- Read material indices
G4int nVoxels = sliceHeader->GetNoVoxels();
//--- If first slice, initiliaze fMateIDs
if( fZSliceHeaders.size() == 1 ) {
fMateIDs = new size_t[fNoFiles*nVoxels];
}
size_t mateID;
G4int voxelCopyNo = (fZSliceHeaders.size()-1)*nVoxels; // number of voxels from previously read slices
for( G4int ii = 0; ii < nVoxels; ii++, voxelCopyNo++ ){
fin >> mateID;
fMateIDs[voxelCopyNo] = mateID;
}
//----- 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)
G4double density;
voxelCopyNo = (fZSliceHeaders.size()-1)*nVoxels; // number of voxels from previously read slices
for( G4int ii = 0; ii < nVoxels; ii++, voxelCopyNo++ ){
fin >> density;
//-- Get material from list of original materials
int mateID = fMateIDs[voxelCopyNo];
G4Material* mateOrig = fOriginalMaterials[mateID];
//-- Get density bin: middle point of the bin in which the current density is included
float densityBin = fDensityDiffs[mateID] * (G4int(density/fDensityDiffs[mateID])+0.5);
//-- Build the new material name
G4String newMateName = mateOrig->GetName()+"__"+ftoa(densityBin);
//-- Look if a material with this name is already created (because a previous voxel was already in this density bin)
size_t im;
for( im = 0; im < fMaterials.size(); im++ ){
if( fMaterials[im]->GetName() == newMateName ) {
break;
}
}
//-- If material is already created use index of this material
if( im != fMaterials.size() ) {
fMateIDs[voxelCopyNo] = im;
//-- else, create the material
} else {
fMaterials.push_back( BuildMaterialWithChangingDensity( mateOrig, densityBin, newMateName ) );
fMateIDs[voxelCopyNo] = fMaterials.size()-1;
}
}
}
//-------------------------------------------------------------
void DicomDetectorConstruction::MergeZSliceHeaders()
{
//----- Images must have the same dimension ...
fZSliceHeaderMerged = new DicomPatientZSliceHeader( *fZSliceHeaders[0] );
for( size_t ii = 1; ii < fZSliceHeaders.size(); ii++ ) {
*fZSliceHeaderMerged += *fZSliceHeaders[ii];
};
}
//-------------------------------------------------------------
G4Material* DicomDetectorConstruction::BuildMaterialWithChangingDensity( const G4Material* origMate, float density, G4String newMateName )
{
//----- Copy original material, but with new density
G4int nelem = origMate->GetNumberOfElements();
G4Material* mate = new G4Material( newMateName, density*g/cm3, nelem, kStateUndefined, STP_Temperature );
for( G4int ii = 0; ii < nelem; ii++ ){
G4double frac = origMate->GetFractionVector()[ii];
G4Element* elem = const_cast<G4Element*>(origMate->GetElement(ii));
mate->AddElement( elem, frac );
}
return mate;
}
//-----------------------------------------------------------------------
G4String DicomDetectorConstruction::ftoa(float flo)
{
char ctmp[100];
gcvt( flo, 10, ctmp );
return G4String(ctmp);
}
//-------------------------------------------------------------
void DicomDetectorConstruction::ConstructPatientContainer()
{
//---- Extract number of voxels and voxel dimensions
nVoxelX = fZSliceHeaderMerged->GetNoVoxelX();
nVoxelY = fZSliceHeaderMerged->GetNoVoxelY();
nVoxelZ = fZSliceHeaderMerged->GetNoVoxelZ();
voxelHalfDimX = fZSliceHeaderMerged->GetVoxelHalfX();
voxelHalfDimY = fZSliceHeaderMerged->GetVoxelHalfY();
voxelHalfDimZ = fZSliceHeaderMerged->GetVoxelHalfZ();
#ifdef G4VERBOSE
G4cout << " nVoxelX " << nVoxelX << " voxelHalfDimX " << voxelHalfDimX <<G4endl;
G4cout << " nVoxelY " << nVoxelY << " voxelHalfDimY " << voxelHalfDimY <<G4endl;
G4cout << " nVoxelZ " << nVoxelZ << " voxelHalfDimZ " << voxelHalfDimZ <<G4endl;
G4cout << " totalPixels " << nVoxelX*nVoxelY*nVoxelZ << G4endl;
#endif
//----- Define the volume that contains all the voxels
container_solid = new G4Box("PhantomContainer",nVoxelX*voxelHalfDimX,nVoxelY*voxelHalfDimY,nVoxelZ*voxelHalfDimZ);
container_logic =
new G4LogicalVolume( container_solid,
fMaterials[0], //the material is not important, it will be fully filled by the voxels
"PhantomContainer",
0, 0, 0 );
//--- Place it on the world
G4double offsetX = (fZSliceHeaderMerged->GetMaxX() + fZSliceHeaderMerged->GetMinX() ) /2.;
G4double offsetY = (fZSliceHeaderMerged->GetMaxY() + fZSliceHeaderMerged->GetMinY() ) /2.;
G4double offsetZ = (fZSliceHeaderMerged->GetMaxZ() + fZSliceHeaderMerged->GetMinZ() ) /2.;
G4ThreeVector posCentreVoxels(offsetX,offsetY,offsetZ);
#ifdef G4VERBOSE
G4cout << " placing voxel container volume at " << posCentreVoxels << G4endl;
#endif
container_phys =
new G4PVPlacement(0, // rotation
posCentreVoxels,
container_logic, // The logic volume
"PhantomContainer", // Name
world_logic, // Mother
false, // No op. bool.
1); // Copy number
}
@@ -51,8 +51,10 @@ DicomEventAction::DicomEventAction():drawFlag("all")
DicomEventAction::~DicomEventAction()
{ }
void DicomEventAction::BeginOfEventAction(const G4Event*)
{ }
void DicomEventAction::BeginOfEventAction(const G4Event* evt)
{
G4cout << "EV: " << evt->GetEventID() << G4endl;
}
void DicomEventAction::EndOfEventAction(const G4Event* evt)
{
@@ -1,388 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// The code was written by :
// *Louis Archambault louis.archambault@phy.ulaval.ca,
// *Luc Beaulieu beaulieu@phy.ulaval.ca
// +Vincent Hubert-Tremblay at tigre.2@sympatico.ca
//
//
// *Centre Hospitalier Universitaire de Quebec (CHUQ),
// Hotel-Dieu de Quebec, departement de Radio-oncologie
// 11 cote du palais. Quebec, QC, Canada, G1R 2J6
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Université Laval, Québec (QC) Canada
//*******************************************************
#include "globals.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4VPhysicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4PVParameterised.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4VisAttributes.hh"
#include "G4Colour.hh"
#include "G4ios.hh"
#include "DicomGeometry.hh"
#include "DicomPatientParameterisation.hh"
#include "DicomPatientConstructor.hh"
#include "DicomConfiguration.hh"
DicomGeometry::DicomGeometry()
{
patientConstructor = new DicomPatientConstructor();
trabecularBone = 0;
denseBone = 0;
liver = 0;
muscle = 0;
phantom = 0;
breast = 0;
adiposeTissue = 0;
lungexhale = 0;
lunginhale = 0;
air = 0;
solidWorld = 0;
logicWorld = 0;
physiWorld = 0;
parameterisedPhysVolume = 0;
physicalLungINhale = 0;
}
DicomGeometry::~DicomGeometry()
{
delete air;
delete lunginhale;
delete lungexhale;
delete adiposeTissue;
delete breast;
delete phantom;
delete muscle;
delete liver;
delete denseBone;
delete trabecularBone;
delete patientConstructor;
}
void DicomGeometry::InitialisationOfMaterials()
{
// Creating elements :
G4double z, a, density;
G4String name, symbol;
G4Element* elC = new G4Element( name = "Carbon",
symbol = "C",
z = 6.0, a = 12.011 * g/mole );
G4Element* elH = new G4Element( name = "Hydrogen",
symbol = "H",
z = 1.0, a = 1.008 * g/mole );
G4Element* elN = new G4Element( name = "Nitrogen",
symbol = "N",
z = 7.0, a = 14.007 * g/mole );
G4Element* elO = new G4Element( name = "Oxygen",
symbol = "O",
z = 8.0, a = 16.00 * g/mole );
G4Element* elNa = new G4Element( name = "Sodium",
symbol = "Na",
z= 11.0, a = 22.98977* g/mole );
G4Element* elS = new G4Element( name = "Sulfur",
symbol = "S",
z = 16.0,a = 32.065* g/mole );
G4Element* elCl = new G4Element( name = "Chlorine",
symbol = "P",
z = 17.0, a = 35.453* g/mole );
G4Element* elK = new G4Element( name = "Potassium",
symbol = "P",
z = 19.0, a = 30.0983* g/mole );
G4Element* elP = new G4Element( name = "Phosphorus",
symbol = "P",
z = 30.0, a = 30.973976* g/mole );
G4Element* elFe = new G4Element( name = "Iron",
symbol = "Fe",
z = 26, a = 56.845* g/mole );
G4Element* elMg = new G4Element( name = "Magnesium",
symbol = "Mg",
z = 12.0, a = 24.3050* g/mole );
G4Element* elCa = new G4Element( name="Calcium",
symbol = "Ca",
z = 20.0, a = 40.078* g/mole );
// Creating Materials :
G4int numberofElements;
// Trabecular Bone
trabecularBone = new G4Material( "SkeletonSpongiosa",
density = 1159*kg/m3,
numberofElements = 12 );
trabecularBone->AddElement(elH,0.085);
trabecularBone->AddElement(elC,0.404);
trabecularBone->AddElement(elN,0.058);
trabecularBone->AddElement(elO,0.367);
trabecularBone->AddElement(elNa,0.001);
trabecularBone->AddElement(elMg,0.001);
trabecularBone->AddElement(elP,0.034);
trabecularBone->AddElement(elS,0.002);
trabecularBone->AddElement(elCl,0.002);
trabecularBone->AddElement(elK,0.001);
trabecularBone->AddElement(elCa,0.044);
trabecularBone->AddElement(elFe,0.001);
// dense Bone
denseBone = new G4Material( "SkeletonRibs",
density = 1575*kg/m3,
numberofElements = 11 );
denseBone->AddElement(elH,0.056);
denseBone->AddElement(elC,0.235);
denseBone->AddElement(elN,0.050);
denseBone->AddElement(elO,0.434);
denseBone->AddElement(elNa,0.001);
denseBone->AddElement(elMg,0.001);
denseBone->AddElement(elP,0.072);
denseBone->AddElement(elS,0.003);
denseBone->AddElement(elCl,0.001);
denseBone->AddElement(elK,0.001);
denseBone->AddElement(elCa,0.146);
// Liver
liver = new G4Material( "Liver",
density = 1071*kg/m3,
numberofElements = 9);
liver->AddElement(elH,0.102);
liver->AddElement(elC,0.139);
liver->AddElement(elN,0.030);
liver->AddElement(elO,0.716);
liver->AddElement(elNa,0.002);
liver->AddElement(elP,0.003);
liver->AddElement(elS,0.003);
liver->AddElement(elCl,0.002);
liver->AddElement(elK,0.003);
// Muscle
muscle = new G4Material( "Muscle",
density = 1061*kg/m3,
numberofElements = 9 );
muscle->AddElement(elH,0.102);
muscle->AddElement(elC,0.143);
muscle->AddElement(elN,0.034);
muscle->AddElement(elO,0.710);
muscle->AddElement(elNa,0.001);
muscle->AddElement(elP,0.002);
muscle->AddElement(elS,0.003);
muscle->AddElement(elCl,0.001);
muscle->AddElement(elK,0.004);
// Phantom
phantom = new G4Material( "Phantom",
density = 1.018*kg/m3,
numberofElements = 2 );
phantom->AddElement(elH,0.112);
phantom->AddElement(elO,0.888);
// Breast
breast = new G4Material( "Breast",
density = 990*kg/m3,
numberofElements = 8 );
breast->AddElement(elH,0.109);
breast->AddElement(elC,0.506);
breast->AddElement(elN,0.023);
breast->AddElement(elO,0.358);
breast->AddElement(elNa,0.001);
breast->AddElement(elP,0.001);
breast->AddElement(elS,0.001);
breast->AddElement(elCl,0.001);
// Adipose tissue
adiposeTissue = new G4Material( "adiposeTissue",
density = 967*kg/m3,
numberofElements = 7);
adiposeTissue->AddElement(elH,0.114);
adiposeTissue->AddElement(elC,0.598);
adiposeTissue->AddElement(elN,0.007);
adiposeTissue->AddElement(elO,0.278);
adiposeTissue->AddElement(elNa,0.001);
adiposeTissue->AddElement(elS,0.001);
adiposeTissue->AddElement(elCl,0.001);
lungexhale = new G4Material( "lungExhale",
density = 508*kg/m3,
numberofElements = 9 );
lungexhale->AddElement(elH,0.103);
lungexhale->AddElement(elC,0.105);
lungexhale->AddElement(elN,0.031);
lungexhale->AddElement(elO,0.749);
lungexhale->AddElement(elNa,0.002);
lungexhale->AddElement(elP,0.002);
lungexhale->AddElement(elS,0.003);
lungexhale->AddElement(elCl,0.002);
lungexhale->AddElement(elK,0.003);
// LungINhale
lunginhale = new G4Material( "lungInhale",
density = 217*kg/m3,
numberofElements = 9);
lunginhale->AddElement(elH,0.103);
lunginhale->AddElement(elC,0.105);
lunginhale->AddElement(elN,0.031);
lunginhale->AddElement(elO,0.749);
lunginhale->AddElement(elNa,0.002);
lunginhale->AddElement(elP,0.002);
lunginhale->AddElement(elS,0.003);
lunginhale->AddElement(elCl,0.002);
lunginhale->AddElement(elK,0.003);
// Air
air = new G4Material( "Air",
1.290*mg/cm3,
numberofElements = 2 );
air->AddElement(elN, 0.7);
air->AddElement(elO, 0.3);
}
void DicomGeometry::PatientConstruction()
{
DicomConfiguration readConfiguration;
readConfiguration.ReadDataFile();
// images must have the same dimension ...
// open a .g4 file to read some values ...
G4int compressionUsed = readConfiguration.IsCompressionUsed();
G4double sliceThickness = readConfiguration.GetSliceThickness();
G4double xPixelSpacing = readConfiguration.GetXPixelSpacing();
G4double yPixelSpacing = readConfiguration.GetYPixelSpacing();
G4int totalNumberOfFile = readConfiguration.GetTotalNumberOfFile();
G4int totalRows = readConfiguration.GetTotalRows();
G4int totalColumns = readConfiguration.GetTotalColumns();
G4double patientX = (compressionUsed*(xPixelSpacing)/2.0) *mm;
G4double patientY = (compressionUsed*(yPixelSpacing)/2.0) *mm;
G4double patientZ = ((sliceThickness/2.0) *mm);
G4VisAttributes* visualisationAttribute = new G4VisAttributes();
visualisationAttribute->SetForceSolid(false);
visualisationAttribute->SetColour( 1.,
0.,
0.,
1. );
G4double middleLocationValue;
G4double maxsl = -999. , minsl = 999.;
for ( G4int i=0; i< totalNumberOfFile;i++ )
{
G4double sliceLoc = readConfiguration.GetSliceLocation()[i];
if(sliceLoc > maxsl) maxsl = sliceLoc;
if(sliceLoc < minsl) minsl = sliceLoc;
}
middleLocationValue = (maxsl + minsl)/2.;
//Building up the parameterisation ...
G4Box* parameterisedBox = new G4Box( "Parameterisation_Mother",
totalColumns*(xPixelSpacing)/2.*mm,
totalRows*(yPixelSpacing)/2.*mm,
(maxsl-minsl+sliceThickness)/2.*mm);
G4LogicalVolume* parameterisedLogicalvolume =
new G4LogicalVolume( parameterisedBox,
air,
"Parameterisation_Mother (logical)" );
parameterisedLogicalvolume->SetVisAttributes(visualisationAttribute);
G4ThreeVector origin( 0.*mm,0.*mm,middleLocationValue*mm );
parameterisedPhysVolume = new G4PVPlacement( 0,
origin,
parameterisedLogicalvolume,
"Parameterisation_Mother_placement",
logicWorld,
false,
0 );
G4Box* LungINhale = new G4Box( "LungINhale", patientX, patientY, patientZ);
G4LogicalVolume* logicLungInHale = new G4LogicalVolume(LungINhale,lunginhale,"Logical_LungINhale",0,0,0);
// ---- MGP ---- Numbers (2.0, 0.207) to be removed from code; move to const
G4int numberOfVoxels = patientConstructor->FindingNbOfVoxels(2.0,0.207);
G4VPVParameterisation* paramLungINhale = new DicomPatientParameterisation
( numberOfVoxels,
2.0 , 0.207 ,
lunginhale,
lungexhale,
adiposeTissue,
breast,
phantom,
muscle,
liver,
denseBone,
trabecularBone );
physicalLungINhale =
new G4PVParameterised( "Physical_LungINhale" ,
logicLungInHale,
parameterisedLogicalvolume,
kZAxis, numberOfVoxels,
paramLungINhale );
// delete ReadConfiguration;
}
G4VPhysicalVolume* DicomGeometry::Construct()
{
InitialisationOfMaterials();
G4double worldXDimension = 1.*m;
G4double worldYDimension = 1.*m;
G4double worldZDimension = 1.*m;
solidWorld = new G4Box( "WorldSolid",
worldXDimension,
worldYDimension,
worldZDimension );
logicWorld = new G4LogicalVolume( solidWorld,
air,
"WorldLogical",
0, 0, 0 );
physiWorld = new G4PVPlacement( 0,
G4ThreeVector(0,0,0),
"World",
logicWorld,
0,
false,
0 );
PatientConstruction();
return physiWorld;
}
@@ -35,7 +35,7 @@
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Universit-Aé Laval, Québec (QC) Canada$)B
// + Universit.A Laval, Qubec (QC) Canada
//*******************************************************
//
//*******************************************************
@@ -45,7 +45,7 @@
// DicomHandler.cc :
// - Handling of DICM images
// - Reading headers and pixels
// - Transforming pixel to density and creating *.g4
// - Transforming pixel to density and creating *.g4dcm
// files
// - Definitions are in DicomHandler.hh
//*******************************************************
@@ -61,7 +61,7 @@
DicomHandler::DicomHandler()
: DATABUFFSIZE(8192), LINEBUFFSIZE(128), FILENAMESIZE(512),
compression(0), max(0), rows(0), columns(0),
compression(0), nFiles(0), rows(0), columns(0),
bitAllocated(0), maxPixelValue(0), minPixelValue(0),
pixelSpacingX(0.), pixelSpacingY(0.),
sliceThickness(0.), sliceLocation(0.),
@@ -75,8 +75,9 @@ DicomHandler::~DicomHandler() {
;
}
G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
G4int DicomHandler::ReadFile(FILE *dicom, char * filename2)
{
G4cout << " ReadFile " << filename2 << G4endl;
G4int returnvalue = 0;
char * buffer = new char[LINEBUFFSIZE];
@@ -108,10 +109,10 @@ G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
readElementId = 0;
// group ID
std::fread(buffer, 2, 1, dicom);
getValue(buffer, readGroupId);
GetValue(buffer, readGroupId);
// element ID
std::fread(buffer, 2, 1, dicom);
getValue(buffer, readElementId);
GetValue(buffer, readElementId);
// Creating a tag to be identified afterward
G4int tagDictionary = readGroupId*0x10000 + readElementId;
@@ -119,7 +120,7 @@ G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
// VR or element length
std::fread(buffer,2,1,dicom);
getValue(buffer, elementLength2);
GetValue(buffer, elementLength2);
// If value representation (VR) is OB, OW, SQ, UN,
//the next length is 32 bits
@@ -133,7 +134,7 @@ G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
// element length
std::fread(buffer, 4, 1, dicom);
getValue(buffer, elementLength4);
GetValue(buffer, elementLength4);
// beginning of the pixels
if(tagDictionary == 0x7FE00010) break;
@@ -147,7 +148,7 @@ G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
if(!implicitEndian || readGroupId == 2) {
// element length (2 bytes)
std::fread(buffer, 2, 1, dicom);
getValue(buffer, elementLength2);
GetValue(buffer, elementLength2);
elementLength4 = elementLength2;
} else {
@@ -157,7 +158,7 @@ G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
exit(-10);
}
std::fread(buffer, 4, 1, dicom);
getValue(buffer, elementLength4);
GetValue(buffer, elementLength4);
}
// beginning of the pixels
@@ -169,12 +170,35 @@ G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
// NULL termination
data[elementLength4] = '\0';
// analyzing inforamtion
getInformation(tagDictionary, data);
// analyzing information
GetInformation(tagDictionary, data);
}
// Creating files to store information
storeInformation(filename2);
std::ofstream foutG4DCM;
G4String fnameG4DCM = G4String(filename2) + ".g4dcm";
foutG4DCM.open(fnameG4DCM);
G4cout << " opened fnameG4DCM file " << fnameG4DCM << G4endl;
foutG4DCM << fMaterialIndices.size() << G4endl;
//--- Write materials
size_t ii = 0;
std::map<G4double,G4String>::const_iterator ite;
for( ite = fMaterialIndices.begin(); ite != fMaterialIndices.end(); ite++, ii++ ){
foutG4DCM << ii << " " << (*ite).second << G4endl;
}
//--- Write number of voxels (assume only one voxel in Z)
foutG4DCM << rows/compression << " " << columns/compression << " 1 " << G4endl;
//--- Write minimum and maximum extensions
foutG4DCM << -pixelSpacingX*rows/2 << " " << pixelSpacingX*rows/2 << G4endl;
foutG4DCM << -pixelSpacingY*columns/2 << " " << pixelSpacingY*columns/2 << G4endl;
foutG4DCM << sliceLocation-sliceThickness/2. << " " << sliceLocation+sliceThickness/2. << G4endl;
ReadData( dicom, filename2 );
StoreData( foutG4DCM );
foutG4DCM.close();
//
delete [] buffer;
@@ -184,35 +208,35 @@ G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
}
//
void DicomHandler::getInformation(G4int & tagDictionary, char * data) {
void DicomHandler::GetInformation(G4int & tagDictionary, char * data) {
if(tagDictionary == 0x00280010 ) { // Number of Rows
getValue(data, rows);
GetValue(data, rows);
std::printf("[0x00280010] Rows -> %i\n",rows);
} else if(tagDictionary == 0x00280011 ) { // Number of columns
getValue(data, columns);
GetValue(data, columns);
std::printf("[0x00280011] Columns -> %i\n",columns);
} else if(tagDictionary == 0x00280102 ) { // High bits ( not used )
short highBits;
getValue(data, highBits);
GetValue(data, highBits);
std::printf("[0x00280102] High bits -> %i\n",highBits);
} else if(tagDictionary == 0x00280100 ) { // Bits allocated
getValue(data, bitAllocated);
GetValue(data, bitAllocated);
std::printf("[0x00280100] Bits allocated -> %i\n", bitAllocated);
} else if(tagDictionary == 0x00280101 ) { // Bits stored ( not used )
short bitStored;
getValue(data, bitStored);
GetValue(data, bitStored);
std::printf("[0x00280101] Bits stored -> %i\n",bitStored);
} else if(tagDictionary == 0x00280106 ) { // Min. pixel value
getValue(data, minPixelValue);
GetValue(data, minPixelValue);
std::printf("[0x00280106] Min. pixel value -> %i\n", minPixelValue);
} else if(tagDictionary == 0x00280107 ) { // Max. pixel value
getValue(data, maxPixelValue);
GetValue(data, maxPixelValue);
std::printf("[0x00280107] Max. pixel value -> %i\n", maxPixelValue);
} else if(tagDictionary == 0x00281053) { // Rescale slope
@@ -324,68 +348,131 @@ void DicomHandler::getInformation(G4int & tagDictionary, char * data) {
}
//
void DicomHandler::storeInformation(char * _filename) {
void DicomHandler::StoreData(std::ofstream& foutG4DCM)
{
G4int mean;
G4double density;
G4bool overflow = false;
G4int cpt=1;
char * compressionbuf = new char[LINEBUFFSIZE];
char * maxbuf = new char[LINEBUFFSIZE];
char * filename = new char[FILENAMESIZE];
compression = 0;
max = 0;
FILE* configuration;
configuration = std::fopen("Data.dat","r");
if( configuration != 0 ) {
std::fscanf(configuration,"%s",compressionbuf);
compression = atoi(compressionbuf);
std::fscanf(configuration,"%s",maxbuf);
max = atoi(maxbuf);
std::fclose(configuration);
} else {
std::printf("### WARNING, file Data.dat not here !!!\n");
exit(1);
//----- Print indices of material
if(compression == 1) { // no compression: each pixel has a density value)
for( G4int ww = 0; ww < rows; ww++) {
for( G4int xx = 0; xx < columns; xx++) {
mean = tab[ww][xx];
density = Pixel2density(mean);
foutG4DCM << GetMaterialIndex( density ) << " ";
}
foutG4DCM << G4endl;
}
} else {
// density value is the average of a square region of
// compression*compression pixels
for(G4int ww = 0; ww < rows ;ww += compression ) {
for(G4int xx = 0; xx < columns ;xx +=compression ) {
overflow = false;
mean = 0;
for(int sumx = 0; sumx < compression; sumx++) {
for(int sumy = 0; sumy < compression; sumy++) {
if(ww+sumy >= rows || xx+sumx >= columns) overflow = true;
mean += tab[ww+sumy][xx+sumx];
}
if(overflow) break;
}
mean /= compression*compression;
cpt = 1;
if(!overflow) {
G4double density = Pixel2density(mean);
foutG4DCM << GetMaterialIndex( density ) << " ";
}
}
foutG4DCM << G4endl;
}
}
FILE* dat;
std::sprintf(filename,"%s.dat", _filename);
dat = std::fopen(filename,"w+");
// Note: the .dat files contain basic information on the images.
//----- Print densities
if(compression == 1) { // no compression: each pixel has a density value)
for( G4int ww = 0; ww < rows; ww++) {
for( G4int xx = 0; xx < columns; xx++) {
mean = tab[ww][xx];
density = Pixel2density(mean);
foutG4DCM << density << " ";
if( xx%8 == 3 ) foutG4DCM << G4endl; // just for nicer reading
}
}
} else {
// density value is the average of a square region of
// compression*compression pixels
for(G4int ww = 0; ww < rows ;ww += compression ) {
for(G4int xx = 0; xx < columns ;xx +=compression ) {
overflow = false;
mean = 0;
for(int sumx = 0; sumx < compression; sumx++) {
for(int sumy = 0; sumy < compression; sumy++) {
if(ww+sumy >= rows || xx+sumx >= columns) overflow = true;
mean += tab[ww+sumy][xx+sumx];
}
if(overflow) break;
}
mean /= compression*compression;
cpt = 1;
if(!overflow) {
G4double density = Pixel2density(mean);
foutG4DCM << density << " ";
if( xx/compression%8 == 3 ) foutG4DCM << G4endl; // just for nicer reading
}
}
}
std::fprintf(dat,"Rows,columns(#): %8i %8i\n",rows,columns);
std::fprintf(dat,"PixelSpacing_X,Y(mm): %8f %8f\n",
pixelSpacingX,pixelSpacingY);
std::fprintf(dat,"SliceThickness(mm): %8f\n",sliceThickness);
std::fprintf(dat,"SliceLocation(mm): %8f\n",sliceLocation);
std::fclose(dat);
}
delete [] compressionbuf;
delete [] maxbuf;
delete [] filename;
}
void DicomHandler::ReadMaterialIndices( std::ifstream& finData)
{
size_t nMate;
G4String mateName;
G4double densityMax;
finData >> nMate;
G4cout << " ReadMaterialIndices " << nMate << G4endl;
for( size_t ii = 0; ii < nMate; ii++ ){
finData >> mateName >> densityMax;
fMaterialIndices[densityMax] = mateName;
G4cout << ii << " ReadMaterialIndices " << mateName << " " << densityMax << G4endl;
}
}
size_t DicomHandler::GetMaterialIndex( G4double density )
{
size_t mateID;
std::map<G4double,G4String>::reverse_iterator ite;
G4int ii = fMaterialIndices.size();
for( ite = fMaterialIndices.rbegin(); ite != fMaterialIndices.rend(); ite++, ii-- ) {
if( density >= (*ite).first ) {
break;
}
}
//- G4cout << " GetMaterialIndex " << density << " = " << ii << G4endl;
return ii;
}
//
G4int DicomHandler::readData(FILE *dicom,char * filename2)
G4int DicomHandler::ReadData(FILE *dicom,char * filename2)
{
G4int returnvalue = 0;
char * compressionbuf = new char[LINEBUFFSIZE];
char * maxbuf = new char[LINEBUFFSIZE];
short compression = 0;
G4int max = 0;
FILE* configuration = std::fopen("Data.dat","r");
std::fscanf(configuration,"%s",compressionbuf);
compression = atoi(compressionbuf);
std::fscanf(configuration,"%s",maxbuf);
max = atoi(maxbuf);
std::fclose(configuration);
// READING THE PIXELS :
G4int w = 0;
G4int len = 0;
G4int** tab = new G4int*[rows];
tab = new G4int*[rows];
for ( G4int i = 0; i < rows; i ++ ) {
tab[i] = new G4int[columns];
}
@@ -416,7 +503,7 @@ G4int DicomHandler::readData(FILE *dicom,char * filename2)
for( G4int i = 0; i < columns; i++) {
w++;
std::fread(sbuff, 2, 1, dicom);
getValue(sbuff, pixel);
GetValue(sbuff, pixel);
tab[j][i] = pixel*rescaleSlope + rescaleIntercept;
}
}
@@ -455,7 +542,7 @@ G4int DicomHandler::readData(FILE *dicom,char * filename2)
for( G4int ww = 0; ww < rows; ww++) {
for( G4int xx = 0; xx < columns; xx++) {
mean = tab[ww][xx];
density = pixel2density(mean);
density = Pixel2density(mean);
std::fwrite(&density, sizeof(G4double), 1, processed);
}
}
@@ -478,7 +565,7 @@ G4int DicomHandler::readData(FILE *dicom,char * filename2)
cpt = 1;
if(!overflow) {
G4double density = pixel2density(mean);
G4double density = Pixel2density(mean);
std::fwrite(&density, sizeof(G4double), 1, processed);
}
}
@@ -487,14 +574,13 @@ G4int DicomHandler::readData(FILE *dicom,char * filename2)
}
std::fclose(processed);
delete [] compressionbuf;
delete [] maxbuf;
delete [] nameProcessed;
for ( G4int i = 0; i < rows; i ++ ) {
/* for ( G4int i = 0; i < rows; i ++ ) {
delete [] tab[i];
}
delete [] tab;
*/
return returnvalue;
}
@@ -511,7 +597,7 @@ G4int DicomHandler::readData(FILE *dicom,char * filename2)
}
*/
G4double DicomHandler::pixel2density(G4int pixel)
G4double DicomHandler::Pixel2density(G4int pixel)
{
G4double density = -1.;
G4int nbrequali = 0;
@@ -560,11 +646,10 @@ G4double DicomHandler::pixel2density(G4int pixel)
}
void DicomHandler::checkFileFormat()
void DicomHandler::CheckFileFormat()
{
std::ifstream checkData("Data.dat");
char * oneLine = new char[128];
G4int nbImages;
if(!(checkData.is_open())) { //Check existance of Data.dat
@@ -575,30 +660,33 @@ void DicomHandler::checkFileFormat()
exit(0);
}
checkData >> nbImages;
checkData >> nbImages;
checkData >> compression;
checkData >> nFiles;
G4String oneName;
checkData.getline(oneLine,100);
std::ifstream testExistence;
G4bool existAlready = true;
for(G4int rep = 0; rep < nbImages; rep++) {
checkData.getline(oneLine,100);
oneName = oneLine;
oneName += ".g4"; // create dicomFile.g4
testExistence.open(oneName.data());
if(!(testExistence.is_open())) {
existAlready = false;
testExistence.clear();
testExistence.close();
break;
}
for(G4int rep = 0; rep < nFiles; rep++) {
checkData.getline(oneLine,100);
oneName = oneLine;
oneName += ".g4dcm"; // create dicomFile.g4dcm
G4cout << nFiles << " test file " << oneName << G4endl;
testExistence.open(oneName.data());
if(!(testExistence.is_open())) {
existAlready = false;
testExistence.clear();
testExistence.close();
}
testExistence.clear();
testExistence.close();
}
ReadMaterialIndices( checkData );
checkData.close();
delete [] oneLine;
if( existAlready == false ) { // The files *.g4 have to be created
if( existAlready == false ) { // The files *.g4dcm have to be created
G4cout << "\nAll the necessary images were not found in processed form, starting "
<< "with .dcm images\n";
@@ -615,9 +703,10 @@ void DicomHandler::checkFileFormat()
std::fscanf(lecturePref,"%s",compressionc);
compression = atoi(compressionc);
std::fscanf(lecturePref,"%s",maxc);
max = atoi(maxc);
nFiles = atoi(maxc);
G4cout << " nFiles " << nFiles << G4endl;
for( G4int i = 1; i <= max; i++ ) { // Begin loop on filenames
for( G4int i = 1; i <= nFiles; i++ ) { // Begin loop on filenames
std::fscanf(lecturePref,"%s",inputFile);
std::sprintf(name,"%s.dcm",inputFile);
@@ -629,11 +718,9 @@ void DicomHandler::checkFileFormat()
// 1. reading the header
// 2. reading the pixel data and store the density in Moyenne.dat
if( dicom != 0 ) {
readHeader(dicom,inputFile);
readData(dicom,inputFile);
ReadFile(dicom,inputFile);
} else {
G4cout << "\nError opening file : " << name << G4endl;
exit(0);
}
std::fclose(dicom);
}
@@ -650,7 +737,7 @@ void DicomHandler::checkFileFormat()
template <class Type>
void DicomHandler::getValue(char * _val, Type & _rval) {
void DicomHandler::GetValue(char * _val, Type & _rval) {
#if BYTE_ORDER == BIG_ENDIAN
if(littleEndian) { // little endian
@@ -0,0 +1,122 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
///////////////////////////////////////////////////////////////////////////////
#include "DicomNestedPhantomParameterisation.hh"
#include "G4VPhysicalVolume.hh"
#include "G4VTouchable.hh"
#include "G4ThreeVector.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4Material.hh"
DicomNestedPhantomParameterisation::DicomNestedPhantomParameterisation(
const G4ThreeVector& voxelSize,
std::vector<G4Material*>& mat):
G4VNestedParameterisation(),fdX(voxelSize.x()),fdY(voxelSize.y()),fdZ(voxelSize.z()),fMaterials(mat)
{
// Position of voxels.
// x and y positions are already defined in DetectorConstruction
// by using replicated volume. Here only we need to define is z positions of voxes.
}
DicomNestedPhantomParameterisation::~DicomNestedPhantomParameterisation()
{
}
void DicomNestedPhantomParameterisation::SetNoVoxel( size_t nx, size_t ny, size_t nz )
{
fnX = nx;
fnY = ny;
fnZ = nz;
}
//
// Material assignment to geometry.
//
G4Material* DicomNestedPhantomParameterisation::ComputeMaterial(G4VPhysicalVolume* ,
const G4int copyNoZ,
const G4VTouchable* parentTouch)
{
if(parentTouch==0) return fMaterials[0]; // protection for initialization and vis at idle state
// Copy number of voxels.
// Copy number of X and Y are obtained from replication number.
// Copy nymber of Z is the copy number of current voxel.
G4int ix = parentTouch->GetReplicaNumber(0);
G4int iy = parentTouch->GetReplicaNumber(1);
G4int iz = copyNoZ;
G4int copyNo = ix + fnZ*iy + fnX*fnY*iz;
size_t matIndex = GetMaterialIndex(copyNo);
return fMaterials[ matIndex ];
}
//------------------------------------------------------------------
size_t DicomNestedPhantomParameterisation::
GetMaterialIndex( size_t copyNo ) const
{
return *(fMaterialIndices+copyNo);
}
//
// Number of Materials
// Material scanner is required for preparing physics tables and so on before
// stating simulation, so that G4 has to know number of materials.
G4int DicomNestedPhantomParameterisation::GetNumberOfMaterials() const{
return fMaterials.size();
}
//
// GetMaterial
// This is needed for material scanner and realizing geometry.
//
G4Material* DicomNestedPhantomParameterisation::GetMaterial(G4int i) const{
return fMaterials[i];
}
//
// Transformation of voxels.
//
void DicomNestedPhantomParameterisation::ComputeTransformation(const G4int copyNo,
G4VPhysicalVolume* physVol)const{
G4ThreeVector position(0.,0.,(2*copyNo+1)*fdZ - fdZ*fnZ);
physVol->SetTranslation(position);
}
//
// Dimensions are always same in this RE02 example.
//
void DicomNestedPhantomParameterisation::ComputeDimensions(G4Box& box,
const G4int ,
const G4VPhysicalVolume* ) const{
box.SetXHalfLength(fdX);
box.SetYHalfLength(fdY);
box.SetZHalfLength(fdZ);
}
@@ -1,157 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// The code was written by :
// *Louis Archambault louis.archambault@phy.ulaval.ca,
// *Luc Beaulieu beaulieu@phy.ulaval.ca
// +Vincent Hubert-Tremblay at tigre.2@sympatico.ca
//
//
// *Centre Hospitalier Universitaire de Quebec (CHUQ),
// Hotel-Dieu de Quebec, departement de Radio-oncologie
// 11 cote du palais. Quebec, QC, Canada, G1R 2J6
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Université Laval, Québec (QC) Canada
//*******************************************************
#include "DicomOctree.hh"
#include "DicomOctreeNode.hh"
#include "DicomOctreeMiddleNode.hh"
#include "DicomOctreeTerminalNode.hh"
#include "G4ios.hh"
DicomOctree::DicomOctree( G4int noLevels, G4double size )
{
std::cout << "++++++ DicomOctree was instantiated now." << std::endl;
mNoLevels = noLevels;
mSize = size;
mRoot = new DicomOctreeMiddleNode(0);
}
DicomOctree::~DicomOctree()
{
delete mRoot;
mRoot = 0;
}
DicomOctreeNode* DicomOctree::CreateNode( G4double nodeX, G4double nodeY, G4double nodeZ, G4int level )
{
DicomOctreeNode* current = mRoot;
G4double currentX = 0;
G4double currentY = 0;
G4double currentZ = 0;
indexChild = 8;
for ( G4int i = 0; i < indexChild; i++ ) // Make children
{
G4double childLevelResolution = (1 << (i+1) );
G4double childSize = mSize / childLevelResolution;
G4int dirX = G4int( nodeX >= currentX + childSize );
G4int dirY = G4int( nodeY >= currentY + childSize );
G4int dirZ = G4int( nodeZ >= currentZ + childSize );
G4int direction = dirX + ( dirY << 1 ) + ( dirZ << 2 );
if ( (*current)[direction] == 0 )
{
if ( i < level - 1 )
{
(*current)[direction] = new DicomOctreeMiddleNode( current );
} else
{
(*current)[direction] = new DicomOctreeTerminalNode( current );
}
}
current = (*current)[direction];
currentX += dirX*childSize;
currentY += dirY*childSize;
currentZ += dirZ*childSize;
}
return current;
}
DicomOctreeNode* DicomOctree::operator()( G4double nodeX,
G4double nodeY,
G4double nodeZ,
G4int level )
{
DicomOctreeNode* current = mRoot;
G4double currentX = 0;
G4double currentY = 0;
G4double currentZ = 0;
// Make children
for ( G4int i = 0; i < level; i++ )
{
G4double childLevelResolution = ( 1 << (i+1) );
G4double childSize = mSize / childLevelResolution;
G4int dirX = G4int( nodeX >= currentX + childSize );
G4int dirY = G4int( nodeY >= currentY + childSize );
G4int dirZ = G4int( nodeZ >= currentZ + childSize );
G4int direction = dirX + ( dirY << 1 ) + ( dirZ << 2 );
if ( (*current)[direction] == 0 ) return 0;
current = (*current)[direction];
currentX += dirX*childSize;
currentY += dirY*childSize;
currentZ += dirZ*childSize;
}
return current;
}
void DicomOctree::DeleteTree()
{
delete mRoot;
mRoot = 0;
}
void DicomOctree::CountRecursive( DicomOctreeNode* pNode,
G4int rMiddle,
G4int rTerminal )
{
if ( pNode->Type() == MIDDLE_NODE )rMiddle++;
else rTerminal++;
for ( G4int i = 0; i < 8; i++ )
{
if ( (*pNode)[i] != 0 )
CountRecursive( (*pNode)[i], rMiddle, rTerminal );
}
}
G4int DicomOctree::CountMemory( G4int rMiddle, G4int rTerminal )
{
CountRecursive( mRoot, rMiddle, rTerminal );
G4int total = rMiddle*sizeof(DicomOctreeMiddleNode) +
rTerminal*sizeof(DicomOctreeTerminalNode);
return total;
}
@@ -1,83 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// The code was written by :
// *Louis Archambault louis.archambault@phy.ulaval.ca,
// *Luc Beaulieu beaulieu@phy.ulaval.ca
// +Vincent Hubert-Tremblay at tigre.2@sympatico.ca
//
//
// *Centre Hospitalier Universitaire de Quebec (CHUQ),
// Hotel-Dieu de Quebec, departement de Radio-oncologie
// 11 cote du palais. Quebec, QC, Canada, G1R 2J6
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Université Laval, Québec (QC) Canada
//*******************************************************
#include "DicomOctreeNode.hh"
#include "DicomOctreeMiddleNode.hh"
#include "DicomOctree.hh"
DicomOctreeMiddleNode::DicomOctreeMiddleNode()
{
ResetFamily();
}
DicomOctreeMiddleNode::~DicomOctreeMiddleNode()
{
for ( G4int i = 0; i < 8; i++ )
{
if ( mChildren[i] != 0 ) delete mChildren[i];
}
}
void DicomOctreeMiddleNode::ResetFamily()
{
// ---- MGP ---- Remove explicit numbers in code
for ( G4int i = 0; i < 8; i++ ) mChildren[i] = 0;
}
DicomOctreeMiddleNode::DicomOctreeMiddleNode( DicomOctreeNode* pParent ) : DicomOctreeNode( pParent )
{
ResetFamily();
}
G4int DicomOctreeMiddleNode::FindChild( const DicomOctreeNode* pNode )
{
for ( G4int i = 0; i < 8; i++ )
{
if ( mChildren[i] == pNode ) return i;
}
return -1;
}
G4int DicomOctreeMiddleNode::MemSize()
{
return sizeof(DicomOctreeMiddleNode);
}
@@ -1,62 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// The code was written by :
// *Louis Archambault louis.archambault@phy.ulaval.ca,
// *Luc Beaulieu beaulieu@phy.ulaval.ca
// +Vincent Hubert-Tremblay at tigre.2@sympatico.ca
//
//
// *Centre Hospitalier Universitaire de Quebec (CHUQ),
// Hotel-Dieu de Quebec, departement de Radio-oncologie
// 11 cote du palais. Quebec, QC, Canada, G1R 2J6
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Université Laval, Québec (QC) Canada
//*******************************************************
#include <stddef.h>
#include "DicomOctreeNode.hh"
G4int DicomOctreeNode::mInstanceCounter = 0;
DicomOctreeNode::DicomOctreeNode()
{
mParent = 0;
mInstanceCounter++;
}
DicomOctreeNode::~DicomOctreeNode()
{
mInstanceCounter--;
}
DicomOctreeNode::DicomOctreeNode( DicomOctreeNode* pParent )
{
mParent = pParent;
mInstanceCounter++;
}
@@ -1,66 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// The code was written by :
// *Louis Archambault louis.archambault@phy.ulaval.ca,
// *Luc Beaulieu beaulieu@phy.ulaval.ca
// +Vincent Hubert-Tremblay at tigre.2@sympatico.ca
//
//
// *Centre Hospitalier Universitaire de Quebec (CHUQ),
// Hotel-Dieu de Quebec, departement de Radio-oncologie
// 11 cote du palais. Quebec, QC, Canada, G1R 2J6
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Université Laval, Québec (QC) Canada
//*******************************************************
#include "DicomOctreeNode.hh"
#include "DicomOctreeTerminalNode.hh"
DicomOctreeNode* DicomOctreeTerminalNode::mNull = 0;
DicomOctreeTerminalNode::DicomOctreeTerminalNode( DicomOctreeNode* pParent) : DicomOctreeNode( pParent )
{
}
DicomOctreeTerminalNode::~DicomOctreeTerminalNode()
{
}
DicomOctreeNode*& DicomOctreeTerminalNode::operator []( G4int )
{
return mNull;
}
G4int DicomOctreeTerminalNode::MemSize()
{
return sizeof(DicomOctreeTerminalNode);
}
@@ -1,72 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// The code was written by :
// *Louis Archambault louis.archambault@phy.ulaval.ca,
// *Luc Beaulieu beaulieu@phy.ulaval.ca
// +Vincent Hubert-Tremblay at tigre.2@sympatico.ca
//
//
// *Centre Hospitalier Universitaire de Quebec (CHUQ),
// Hotel-Dieu de Quebec, departement de Radio-oncologie
// 11 cote du palais. Quebec, QC, Canada, G1R 2J6
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Université Laval, Québec (QC) Canada
//*******************************************************
//*******************************************************
//
// DicomPatientConstructor.cc :
// - Initialisation of the construction of DICM images
// - Reading contour information included in Plan.roi
// (Region of interest) *** NOT FULLY WORKING YET ***
// - Definitions are in DicomGeometry.hh
//
//*******************************************************
#include "DicomConfiguration.hh"
#include "DicomPatientConstructor.hh"
#include "globals.hh"
G4int DicomPatientConstructor::FindingNbOfVoxels(G4double maxDensity , G4double minDensity) {
DicomConfiguration dicomConfiguration;
G4double density;
G4int npass = 0;
G4int npixels = dicomConfiguration.GetTotalPixels();
for(int i = 0; i < npixels; i++) {
density = dicomConfiguration.GetDensityValue(i);
if(density >= minDensity && density <= maxDensity) npass++;
}
return npass;
}
@@ -1,367 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// The code was written by :
// *Louis Archambault louis.archambault@phy.ulaval.ca,
// *Luc Beaulieu beaulieu@phy.ulaval.ca
// +Vincent Hubert-Tremblay at tigre.2@sympatico.ca
//
//
// *Centre Hospitalier Universitaire de Quebec (CHUQ),
// Hotel-Dieu de Quebec, departement de Radio-oncologie
// 11 cote du palais. Quebec, QC, Canada, G1R 2J6
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Universit.A Laval, Qubec (QC) Canada
//*******************************************************
#include "DicomPatientParameterisation.hh"
#include "DicomConfiguration.hh"
#include "G4VPhysicalVolume.hh"
#include "G4ThreeVector.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4Material.hh"
#include "G4VisAttributes.hh"
DicomPatientParameterisation::DicomPatientParameterisation(G4int, // NoVoxels,
G4double maxDensity,
G4double minDensity ,
G4Material* lunginhale,
G4Material* lungexhale,
G4Material* adipose,
G4Material* breast,
G4Material* phantom,
G4Material* muscle,
G4Material* liver,
G4Material* denseBone,
G4Material* trabecularBone) {
lungExhale = lungexhale;
lungInhale = lunginhale;
adiposeTissue = adipose;
breastTissue = breast;
phantomTissue = phantom;
muscleTissue = muscle;
liverTissue = liver;
denseBoneTissue = denseBone;
trabecularBoneTissue = trabecularBone;
density.clear();
DicomConfiguration dicomConfiguration;
// images must have the same dimension
G4int totalNumberOfFile = dicomConfiguration.GetTotalNumberOfFile();
G4double maxsl = -999. , minsl = 999.;
for( G4int i = 0; i < totalNumberOfFile; i++) {
G4double sliceLocation = dicomConfiguration.GetSliceLocation()[i];
if(sliceLocation > maxsl) maxsl = sliceLocation;
if(sliceLocation < minsl) minsl = sliceLocation;
}
middleLocationValue = (maxsl + minsl)*0.5;
//
readColorChart();
G4double alpha;
attributeLungINhale = new G4VisAttributes;
attributeLungINhale->SetColour(getChartColor(ColorChart::CRED, 0.217),
getChartColor(ColorChart::CGREEN, 0.217),
getChartColor(ColorChart::CBLUE, 0.217),
alpha=1.);
attributeLungINhale->SetForceSolid(true);
attributeLungEXhale = new G4VisAttributes;
attributeLungEXhale->SetColour(getChartColor(ColorChart::CRED, 0.508),
getChartColor(ColorChart::CGREEN, 0.508),
getChartColor(ColorChart::CBLUE, 0.508),
alpha=1.);
attributeLungEXhale->SetForceSolid(true);
attributeAdipose = new G4VisAttributes;
attributeAdipose->SetColour(getChartColor(ColorChart::CRED, 0.967),
getChartColor(ColorChart::CGREEN, 0.967),
getChartColor(ColorChart::CBLUE, 0.967),
alpha=1.);
attributeAdipose->SetForceSolid(true);
attributeBreast = new G4VisAttributes;
attributeBreast->SetColour(getChartColor(ColorChart::CRED, 0.99),
getChartColor(ColorChart::CGREEN, 0.99),
getChartColor(ColorChart::CBLUE, 0.99),
alpha=1.);
attributeBreast->SetForceSolid(true);
attributePhantom = new G4VisAttributes;
attributePhantom->SetColour(getChartColor(ColorChart::CRED, 1.018),
getChartColor(ColorChart::CGREEN, 1.018),
getChartColor(ColorChart::CBLUE, 1.018),
alpha=1.);
attributePhantom->SetForceSolid(true);
attributeMuscle = new G4VisAttributes;
attributeMuscle->SetColour(getChartColor(ColorChart::CRED, 1.061),
getChartColor(ColorChart::CGREEN, 1.061),
getChartColor(ColorChart::CBLUE, 1.061),
alpha=1.);
attributeMuscle->SetForceSolid(true);
attributeLiver = new G4VisAttributes;
attributeLiver->SetColour(getChartColor(ColorChart::CRED, 1.071),
getChartColor(ColorChart::CGREEN, 1.071),
getChartColor(ColorChart::CBLUE, 1.071),
alpha=1.);
attributeLiver->SetForceSolid(true);
attributeTrabecularBone = new G4VisAttributes;
attributeTrabecularBone->SetColour(getChartColor(ColorChart::CRED, 1.159),
getChartColor(ColorChart::CGREEN, 1.159),
getChartColor(ColorChart::CBLUE, 1.159),
alpha=1.);
attributeTrabecularBone->SetForceSolid(true);
attributeDenseBone = new G4VisAttributes;
attributeDenseBone->SetColour(getChartColor(ColorChart::CRED, 1.575),
getChartColor(ColorChart::CGREEN, 1.575),
getChartColor(ColorChart::CBLUE, 1.575),
alpha=1.);
attributeDenseBone->SetForceSolid(true);
attributeAir = new G4VisAttributes;
attributeAir->SetColour(getChartColor(ColorChart::CRED, 1.),
getChartColor(ColorChart::CGREEN, 1.),
getChartColor(ColorChart::CBLUE, 1.),
alpha=1.);
attributeAir->SetForceSolid(false);
rows = dicomConfiguration.GetTotalRows();
columns = dicomConfiguration.GetTotalColumns();
compression = dicomConfiguration.GetCompressionValue();
max = dicomConfiguration.GetTotalNumberOfFile();
pixelSpacingX = dicomConfiguration.GetXPixelSpacing();
pixelSpacingY = dicomConfiguration.GetYPixelSpacing();
sliceThickness = dicomConfiguration.GetSliceThickness();
GetDensity( maxDensity , minDensity );
dicomConfiguration.ClearDensityData();
}
DicomPatientParameterisation::~DicomPatientParameterisation() {
// visualisation attributes ...
delete attributeAdipose;
delete attributeLungEXhale;
delete attributeBreast;
delete attributePhantom;
delete attributeMuscle;
delete attributeLiver;
delete attributeTrabecularBone;
delete attributeLungINhale;
delete attributeDenseBone;
delete attributeAir;
// materials ...
delete trabecularBoneTissue;
delete denseBoneTissue;
delete liverTissue;
delete muscleTissue;
delete breastTissue;
delete adiposeTissue;
delete lungInhale;
delete lungExhale;
}
void DicomPatientParameterisation::ComputeTransformation(const G4int copyNo, G4VPhysicalVolume* physVol) const
{
G4double originZ = patientPlacementZ[copyNo]*mm-middleLocationValue*mm-sliceThickness/2;
G4ThreeVector origin( patientPlacementX[copyNo]*mm,
patientPlacementY[copyNo]*mm,
originZ*mm );
physVol->SetTranslation(origin);
}
void DicomPatientParameterisation::ComputeDimensions(G4Box& voxels, const G4int, const G4VPhysicalVolume*) const
{
voxels.SetXHalfLength((pixelSpacingX * compression/2.0) * mm);
voxels.SetYHalfLength((pixelSpacingY * compression/2.0) * mm);
voxels.SetZHalfLength((sliceThickness / 2.0) * mm);
}
G4Material*
DicomPatientParameterisation::ComputeMaterial(const G4int copyNo,
G4VPhysicalVolume* physVol,
const G4VTouchable*)
{
if( density[copyNo] >= 0.207 && density[copyNo] <= 0.227 ) {
physVol->SetName("PhysicalLungINhale");
physVol->GetLogicalVolume()->SetVisAttributes( attributeLungINhale );
return lungInhale;
} else if( density[copyNo] >= 0.481 && density[copyNo] <= 0.534 ) {
physVol->SetName("PhysicalLungEXhale");
physVol->GetLogicalVolume()->SetVisAttributes( attributeLungEXhale );
return lungExhale;
} else if( density[copyNo] >= 0.919 && density[copyNo] <= 0.979 ) {
physVol->SetName("PhysicalAdipose");
physVol->GetLogicalVolume()->SetVisAttributes( attributeAdipose );
return adiposeTissue;
} else if( density[copyNo] > 0.979 && density[copyNo] <= 1.004 ) {
physVol->SetName("PhysicalBreast");
physVol->GetLogicalVolume()->SetVisAttributes( attributeBreast );
return breastTissue;
} else if( density[copyNo] > 1.004 && density[copyNo] <= 1.043 ) {
physVol->SetName("PhysicalPhantom");
physVol->GetLogicalVolume()->SetVisAttributes( attributePhantom );
return phantomTissue;
} else if( density[copyNo] > 1.043 && density[copyNo] <= 1.109 ) {
physVol->SetName("PhysicalMuscle");
physVol->GetLogicalVolume()->SetVisAttributes( attributeMuscle );
return muscleTissue;
} else if( density[copyNo] > 1.109 && density[copyNo] <= 1.113 ) {
physVol->SetName("PhysicalLiver");
physVol->GetLogicalVolume()->SetVisAttributes( attributeLiver );
return liverTissue;
} else if( density[copyNo] > 1.113 && density[copyNo] <= 1.217 ) {
physVol->SetName("PhysicalTrabecularBone");
physVol->GetLogicalVolume()->SetVisAttributes( attributeTrabecularBone );
return trabecularBoneTissue;
} else if( density[copyNo] > 1.496 && density[copyNo] <= 1.654 ) {
physVol->SetName("PhysicalDenseBone");
physVol->GetLogicalVolume()->SetVisAttributes( attributeDenseBone );
return denseBoneTissue;
}
return physVol->GetLogicalVolume()->GetMaterial();
}
void DicomPatientParameterisation::GetDensity(G4double maxdensity, G4double mindensity) {
DicomConfiguration dicomConfiguration;
G4int copyCounter = 0;
G4int totalNumberOfFile = dicomConfiguration.GetTotalNumberOfFile();
G4int lenRows = rows/compression;
G4int lenColumns = columns/compression;
G4double xDimension = (lenColumns*pixelSpacingX)/2;
G4int i = 0;
for( G4int z = 0; z < totalNumberOfFile; z++ ) {
G4double slicePosition = dicomConfiguration.GetSliceLocation()[z];
for( G4int j = 1; j <= lenRows; j++ ) {
for( G4int w = 1; w <= lenColumns; w++ ) {
G4double tissueDensity = dicomConfiguration.GetDensityValue(i++);
if( tissueDensity != -1 ) {
if( tissueDensity >= mindensity && tissueDensity <= maxdensity ) {
density.push_back( tissueDensity );
copyCounter++;
G4double yPixel = (pixelSpacingY/2 + (w-1)*pixelSpacingY);
G4double yDimension = ((lenRows*pixelSpacingX)/2)-(pixelSpacingY/2+(j-1)*pixelSpacingY);
patientPlacementX.push_back( ( compression*(xDimension- yPixel ) ) *mm );
patientPlacementY.push_back( ( compression* yDimension ) *mm );
patientPlacementZ.push_back( ( slicePosition + sliceThickness/2 ) *mm );
}
}
}
}
}
}
void DicomPatientParameterisation::readColorChart() {
std::ifstream cm("Colormap.dat");
if(!cm) {
G4cerr << "Colormap.dat couldn't be opened!!" << G4endl;
numColorChart = 2;
ColorChart cc;
cc.density = 0.;
cc.color[ColorChart::CRED] = 0.;
cc.color[ColorChart::CGREEN] = 0.;
cc.color[ColorChart::CBLUE] = 0.;
cc.alpha = 1.;
colorChart.push_back(cc);
cc.density = 4.;
cc.color[ColorChart::CRED] = 1.;
cc.color[ColorChart::CGREEN] = 1.;
cc.color[ColorChart::CBLUE] = 1.;
cc.alpha = 1.;
colorChart.push_back(cc);
return;
}
cm >> numColorChart;
ColorChart cc;
for(int i = 0; i < numColorChart; i++) {
cm >> cc.density
>> cc.color[ColorChart::CRED]
>> cc.color[ColorChart::CGREEN]
>> cc.color[ColorChart::CBLUE]
>> cc.alpha;
colorChart.push_back(cc);
}
}
G4double DicomPatientParameterisation::getChartColor(G4int CC, G4double density) {
G4double color = 0.;
for(int i = 0; i < numColorChart; i++) {
if(density <= colorChart[i].density) {
G4double w = (density - colorChart[i-1].density)
/(colorChart[i].density - colorChart[i-1].density);
color = w*colorChart[i-1].color[CC] + (1-w)*colorChart[i].color[CC];
return color;
}
}
return color;
}
@@ -0,0 +1,176 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
#include "globals.hh"
#include "G4LogicalVolume.hh"
#include "G4MaterialTable.hh"
#include "G4Material.hh"
#include "G4GeometryTolerance.hh"
#include "DicomPatientZSliceHeader.hh"
//-------------------------------------------------------------
DicomPatientZSliceHeader::DicomPatientZSliceHeader( const DicomPatientZSliceHeader& rhs )
{
fNoVoxelX = rhs.GetNoVoxelX();
fNoVoxelY = rhs.GetNoVoxelY();
fNoVoxelZ = rhs.GetNoVoxelZ();
fMinX = rhs.GetMinX();
fMaxX = rhs.GetMaxX();
fMinY = rhs.GetMinY();
fMaxY = rhs.GetMaxY();
fMinZ = rhs.GetMinZ();
fMaxZ = rhs.GetMaxZ();
fMaterialNames = rhs.GetMaterialNames();
}
//-------------------------------------------------------------
DicomPatientZSliceHeader::DicomPatientZSliceHeader( std::ifstream& fin )
{
//----- Read material indices and names
G4int nmate;
G4String mateindex;
G4String matename;
fin >> nmate;
#ifdef G4VERBOSE
G4cout << " DicomPatientZSliceHeader reading number of materials " << nmate << G4endl;
#endif
for( G4int im = 0; im < nmate; im++ ){
fin >> mateindex >> matename;
#ifdef G4VERBOSE
G4cout << " DicomPatientZSliceHeader reading material " << im << " : " << mateindex << " " << matename << G4endl;
#endif
if( ! CheckMaterialExists( matename ) ) {
G4Exception("DicomPatientZSliceHeader::DicomPatientZSliceHeader","A material is found in file that is not built in the C++ code",FatalErrorInArgument,matename.c_str());
}
fMaterialNames.push_back(matename);
}
//----- Read number of voxels
fin >> fNoVoxelX >> fNoVoxelY >> fNoVoxelZ;
#ifdef G4VERBOSE
G4cout << " Number of voxels " << fNoVoxelX << " " << fNoVoxelY << " " << fNoVoxelZ << G4endl;
#endif
//----- Read minimal and maximal extensions (= walls of patient)
fin >> fMinX >> fMaxX;
fin >> fMinY >> fMaxY;
fin >> fMinZ >> fMaxZ;
#ifdef G4VERBOSE
G4cout << " Extension in X " << fMinX << " " << fMaxX << G4endl
<< " Extension in Y " << fMinY << " " << fMaxY << G4endl
<< " Extension in Z " << fMinZ << " " << fMaxZ << G4endl;
#endif
}
//-------------------------------------------------------------
G4bool DicomPatientZSliceHeader::CheckMaterialExists( const G4String& mateName )
{
G4bool bFound = FALSE;
const G4MaterialTable* matTab = G4Material::GetMaterialTable();
std::vector<G4Material*>::const_iterator matite;
for( matite = matTab->begin(); matite != matTab->end(); matite++ ) {
if( (*matite)->GetName() == mateName ) {
bFound = TRUE;
break;
}
}
return bFound;
}
//-------------------------------------------------------------
void DicomPatientZSliceHeader::operator+=( const DicomPatientZSliceHeader& rhs )
{
*this = *this + rhs;
}
//-------------------------------------------------------------
DicomPatientZSliceHeader DicomPatientZSliceHeader::operator+( const DicomPatientZSliceHeader& rhs )
{
//----- Check that both slices has the same dimensions
if( fNoVoxelX != rhs.GetNoVoxelX()
|| fNoVoxelY != rhs.GetNoVoxelY() ) {
G4cerr << "DicomPatientZSliceHeader error adding two slice headers: !!! Different number of voxels: "
<< " X= " << fNoVoxelX << " =? " << rhs.GetNoVoxelX()
<< " Y= " << fNoVoxelY << " =? " << rhs.GetNoVoxelY()
<< " Z= " << fNoVoxelZ << " =? " << rhs.GetNoVoxelZ()
<< G4endl;
G4Exception("");
}
//----- Check that both slices has the same extensions
if( fMinX != rhs.GetMinX() || fMaxX != rhs.GetMaxX()
|| fMinY != rhs.GetMinY() || fMaxY != rhs.GetMaxY() ) {
G4cerr << "DicomPatientZSliceHeader error adding two slice headers: !!! Different extensions: "
<< " Xmin= " << fMinX << " =? " << rhs.GetMinX()
<< " Xmax= " << fMaxX << " =? " << rhs.GetMaxX()
<< " Ymin= " << fMinY << " =? " << rhs.GetMinY()
<< " Ymax= " << fMaxY << " =? " << rhs.GetMaxY()
<< G4endl;
G4Exception("");
}
//----- Check that both slices has the same materials
std::vector<G4String> fMaterialNames2 = rhs.GetMaterialNames();
if( fMaterialNames.size() != fMaterialNames2.size() ) {
G4cerr << "DicomPatientZSliceHeader error adding two slice headers: !!! Different number of materials: " << fMaterialNames.size() << " =? " << fMaterialNames2.size() << G4endl;
G4Exception("");
}
for( size_t ii = 0; ii < fMaterialNames.size(); ii++ ) {
if( fMaterialNames[ii] != fMaterialNames2[ii] ) {
G4cerr << "DicomPatientZSliceHeader error adding two slice headers: !!! Different material number " << ii << " : " << fMaterialNames[ii] << " =? " << fMaterialNames2[ii] << G4endl;
G4Exception("");
}
}
//----- Check that the slices are contiguous in Z
if( std::fabs( fMinZ - rhs.GetMaxZ() ) > G4GeometryTolerance::GetInstance()->GetRadialTolerance() &&
std::fabs( fMaxZ - rhs.GetMinZ() ) > G4GeometryTolerance::GetInstance()->GetRadialTolerance() ){
G4cerr << "DicomPatientZSliceHeader error adding two slice headers: !!! Slices are not contiguous in Z "
<< " Zmin= " << fMinZ << " & " << rhs.GetMinZ()
<< " Zmax= " << fMaxZ << " & " << rhs.GetMaxZ()
<< G4endl;
G4Exception("");
}
//----- Build slice header copying first one
DicomPatientZSliceHeader temp( *this );
//----- Add data from second slice header
temp.SetMinZ( std::min( fMinZ, rhs.GetMinZ() ) );
temp.SetMaxZ( std::max( fMaxZ, rhs.GetMaxZ() ) );
temp.SetNoVoxelZ( fNoVoxelZ + rhs.GetNoVoxelZ() );
return temp;
}
@@ -0,0 +1,94 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// --------------------------------------------------------------------
#include "DicomPhantomParameterisationColour.hh"
#include "globals.hh"
#include "G4VisAttributes.hh"
#include "G4Material.hh"
#include "G4VPhysicalVolume.hh"
#include "G4LogicalVolume.hh"
//------------------------------------------------------------------
DicomPhantomParameterisationColour::DicomPhantomParameterisationColour()
{
ReadColourData();
}
//------------------------------------------------------------------
DicomPhantomParameterisationColour::~DicomPhantomParameterisationColour()
{
}
//------------------------------------------------------------------
void DicomPhantomParameterisationColour::ReadColourData()
{
//----- Add a G4VisAttributes for materials not defined in file;
G4VisAttributes* blankAtt = new G4VisAttributes;
blankAtt->SetVisibility( FALSE );
fColours["Default"] = blankAtt;
//----- Read file
std::ifstream fin("ColourMap.dat");
G4int nMate;
G4String mateName;
G4double cred, cgreen, cblue, copacity;
fin >> nMate;
for( G4int ii = 0; ii < nMate; ii++ ){
fin >> mateName >> cred >> cgreen >> cblue >> copacity;
G4Colour colour( cred, cgreen, cblue, copacity );
G4VisAttributes* visAtt = new G4VisAttributes( colour );
fColours[mateName] = visAtt;
}
}
//------------------------------------------------------------------
G4Material* DicomPhantomParameterisationColour::
ComputeMaterial(const G4int copyNo, G4VPhysicalVolume * physVol, const G4VTouchable *)
{
G4Material* mate = G4PhantomParameterisation::ComputeMaterial( copyNo, physVol, 0 );
if( physVol ) {
G4String mateName = mate->GetName();
size_t iuu = mateName.find("__");
if( iuu != std::string::npos ) {
mateName = mateName.substr( 0, iuu );
}
std::map<G4String,G4VisAttributes*>::const_iterator ite = fColours.find(mateName);
if( ite != fColours.end() ){
const G4Colour col = ((*ite).second)->GetColour();
physVol->GetLogicalVolume()->SetVisAttributes( (*ite).second );
} else {
physVol->GetLogicalVolume()->SetVisAttributes( (*(fColours.begin()) ).second ); // set it as unseen
}
}
return mate;
}
@@ -36,6 +36,8 @@
// fax (418) 691 5268
//
// + Université Laval, Québec (QC) Canada
//
// History: 30.11.07 P.Arce default cut changed to 1 mm
//*******************************************************
#include "DicomPhysicsList.hh"
@@ -51,8 +53,8 @@
DicomPhysicsList::DicomPhysicsList(): G4VUserPhysicsList()
{
defaultCutValue = 10.*mm;
cutForGamma = 10.*mm;
defaultCutValue = 1.e-3*mm;
cutForGamma = 1.e-3*mm;
cutForElectron = defaultCutValue;
cutForPositron = defaultCutValue;
@@ -43,9 +43,10 @@
#include "G4Event.hh"
#include "G4ParticleGun.hh"
#include "G4ParticleTable.hh"
#include "DicomGeometry.hh"
#include "RegularDicomDetectorConstruction.hh"
#include "G4ParticleDefinition.hh"
#include "Randomize.hh"
#include "CLHEP/Random/RandFlat.h"
DicomPrimaryGeneratorAction::DicomPrimaryGeneratorAction()
{
@@ -65,10 +66,11 @@ void DicomPrimaryGeneratorAction::GeneratePrimaries(G4Event *anEvent)
G4ParticleDefinition* particle
= particleTable->FindParticle(particleName="gamma");
particleGun->SetParticleDefinition(particle);
// ---- MGP ---- Numbers in the code should be replaced by const
particleGun->SetParticleMomentumDirection(G4ThreeVector(1.,0.*cm,0.*cm));
G4ThreeVector dir(2.*CLHEP::RandFlat::shoot()-1.,2.*CLHEP::RandFlat::shoot()-1.,2.*CLHEP::RandFlat::shoot()-1);
dir /= dir.mag();
particleGun->SetParticleMomentumDirection(dir);
particleGun->SetParticleEnergy(5.*MeV);
particleGun->SetParticlePosition(G4ThreeVector(0.,0.,0.));
particleGun->SetParticlePosition(G4ThreeVector(0.,0.,-20.)); // put it close to the patient voxels
particleGun->GeneratePrimaryVertex(anEvent);
}
@@ -0,0 +1,100 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// History:
// Pedro Arce
//
//*******************************************************
#include "globals.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4VPhysicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4PVParameterised.hh"
#include "NestedParamDicomDetectorConstruction.hh"
#include "DicomNestedPhantomParameterisation.hh"
NestedParamDicomDetectorConstruction::NestedParamDicomDetectorConstruction() : DicomDetectorConstruction()
{
}
NestedParamDicomDetectorConstruction::~NestedParamDicomDetectorConstruction()
{
}
//-------------------------------------------------------------
void NestedParamDicomDetectorConstruction::ConstructPatient()
{
#ifdef G4VERBOSE
G4cout << "NestedParamDicomDetectorConstruction::ConstructPatient " << G4endl;
#endif
//----- Replication of Water Phantom Volume.
//--- Y Slice
G4String yRepName("RepY");
G4VSolid* solYRep =
new G4Box(yRepName,nVoxelX*voxelHalfDimX,voxelHalfDimY,nVoxelZ*voxelHalfDimZ);
G4LogicalVolume* logYRep =
new G4LogicalVolume(solYRep,air,yRepName);
new G4PVReplica(yRepName,logYRep,container_logic,kYAxis,nVoxelY,voxelHalfDimY*2.);
//--- X Slice
G4String xRepName("RepX");
G4VSolid* solXRep =
new G4Box(xRepName,voxelHalfDimX,voxelHalfDimY,nVoxelZ*voxelHalfDimZ);
G4LogicalVolume* logXRep =
new G4LogicalVolume(solXRep,air,xRepName);
new G4PVReplica(xRepName,logXRep,logYRep,kXAxis,nVoxelX,voxelHalfDimX*2.);
//----- Voxel solid and logical volumes
//--- Z Slice
G4VSolid* solVoxel =
new G4Box("Patient",voxelHalfDimX,voxelHalfDimY,voxelHalfDimZ);
G4LogicalVolume* logicVoxel = new G4LogicalVolume(solVoxel,air,"Patient");
//
// Parameterisation for transformation of voxels.
// (voxel size is fixed in this example.
// e.g. nested parameterisation handles material and transfomation of voxels.)
G4ThreeVector voxelSize(voxelHalfDimX,voxelHalfDimY,voxelHalfDimZ);
DicomNestedPhantomParameterisation* param
= new DicomNestedPhantomParameterisation(voxelSize,fMaterials);
new G4PVParameterised("Patient", // their name
logicVoxel, // their logical volume
logXRep, // Mother logical volume
kXAxis, // Are placed along this axis
// kUndefined, // Are placed along this axis
nVoxelZ, // Number of cells
param); // Parameterisation.
param->SetMaterialIndices( fMateIDs );
param->SetNoVoxel( nVoxelX, nVoxelY, nVoxelZ );
}
@@ -0,0 +1,98 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// History:
// Pedro Arce
//
//*******************************************************
#include "globals.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4VPhysicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4PVParameterised.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4VisAttributes.hh"
#include "G4Colour.hh"
#include "G4ios.hh"
#include "RegularDicomDetectorConstruction.hh"
#include "DicomPhantomParameterisationColour.hh"
RegularDicomDetectorConstruction::RegularDicomDetectorConstruction() : DicomDetectorConstruction()
{
}
RegularDicomDetectorConstruction::~RegularDicomDetectorConstruction()
{
}
//-------------------------------------------------------------
void RegularDicomDetectorConstruction::ConstructPatient()
{
#ifdef G4VERBOSE
G4cout << "RegularDicomDetectorConstruction::ConstructPatient " << G4endl;
#endif
//----- Create parameterisation
DicomPhantomParameterisationColour* param = new DicomPhantomParameterisationColour();
//----- Set voxel dimensions
param->SetVoxelDimensions( voxelHalfDimX, voxelHalfDimY, voxelHalfDimZ );
//----- Set number of voxels
param->SetNoVoxel( nVoxelX, nVoxelY, nVoxelZ );
//----- Set list of materials
param->SetMaterials( fMaterials );
//----- Set list of material indices: for each voxel it is a number that correspond to the index of its material in the vector of materials defined above
param->SetMaterialIndices( fMateIDs );
//----- Define voxel logical volume
G4Box* voxel_solid = new G4Box( "Voxel", voxelHalfDimX, voxelHalfDimY, voxelHalfDimZ);
G4LogicalVolume* voxel_logic = new G4LogicalVolume(voxel_solid,fMaterials[0],"VoxelLogical",0,0,0); // material is not relevant, it will be changed by the ComputeMaterial method of the parameterisation
//--- Assign the container volume of the parameterisation
param->BuildContainerSolid(container_phys);
//--- Assure yourself that the voxels are completely filling the container volume
param->CheckVoxelsFillContainer( container_solid->GetXHalfLength(),
container_solid->GetYHalfLength(),
container_solid->GetZHalfLength() );
//----- The G4PVParameterised object that uses the created parameterisation should be placed in the container logical volume
G4PVParameterised * patient_phys = new G4PVParameterised("Patient",voxel_logic,container_logic,
kXAxis, nVoxelX*nVoxelY*nVoxelZ, param);
// if axis is set as kUndefined instead of kXAxis, GEANT4 will do an smart voxel optimisation (not needed if G4RegularNavigation is used)
//----- Set this physical volume as having a regular structure of type 1, so that G4RegularNavigation is used
patient_phys->SetRegularStructureId(1); // if not set, G4VoxelNavigation will be used instead
}