Import Geant4 9.1.0 source tree
This commit is contained in:
@@ -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, Qu��bec (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, Qu��bec (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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user