Import Geant4 9.1.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-09 15:37:50 +02:00
parent a8e9364cea
commit 96c8bcd0af
6923 changed files with 198390 additions and 41849 deletions
@@ -1,4 +0,0 @@
Rows,columns(#): 512 512
PixelSpacing_X,Y(mm): 0.976562 0.976562
SliceThickness(mm): 3.000000
SliceLocation(mm): -24.000000
Binary file not shown.
File diff suppressed because it is too large Load Diff
@@ -1,4 +0,0 @@
Rows,columns(#): 512 512
PixelSpacing_X,Y(mm): 0.976562 0.976562
SliceThickness(mm): 3.000000
SliceLocation(mm): -27.000000
Binary file not shown.
File diff suppressed because it is too large Load Diff
@@ -1,4 +0,0 @@
Rows,columns(#): 512 512
PixelSpacing_X,Y(mm): 0.976562 0.976562
SliceThickness(mm): 3.000000
SliceLocation(mm): -30.000000
Binary file not shown.
File diff suppressed because it is too large Load Diff
@@ -1,21 +0,0 @@
19
0.000 0.0 0.0 0.0 1.0
0.207 0.8 0.5 0.5 1.0
0.227 0.8 0.5 0.5 1.0
0.481 0.7 0.7 0.7 1.0
0.534 0.7 0.7 0.7 1.0
0.919 1.0 0.8 0.8 1.0
0.979 1.0 0.8 0.8 1.0
0.980 0.9 0.0 0.9 1.0
1.004 0.9 0.0 0.9 1.0
1.005 0.9 0.8 0.8 1.0
1.043 0.9 0.8 0.8 1.0
1.044 0.8 0.3 0.3 1.0
1.109 0.8 0.3 0.3 1.0
1.114 0.9 0.9 0.9 1.0
1.217 0.9 0.9 0.9 1.0
1.496 1.0 1.0 1.0 1.0
1.856 1.0 1.0 1.0 1.0
2.000 0.8 0.8 0.8 1.0
4.000 0.0 0.0 0.0 1.0
density red green blue opacity
@@ -0,0 +1,12 @@
10
Air 0.0 0.0 0.0 1.0
LungInhale 0.8 0.5 0.5 1.0
LungExhale 0.7 0.7 0.7 1.0
AdiposeTissue 1.0 0.8 0.8 1.0
Breast 0.9 0.0 0.9 1.0
Water 0.9 0.8 0.8 1.0
Muscle 0.8 0.3 0.3 1.0
Liver 0.9 0.9 0.9 1.0
TrabecularBone 1.0 1.0 1.0 1.0
DenseBone 0.8 0.8 0.8 1.0
material red green blue opacity
+11 -15
View File
@@ -3,20 +3,16 @@
14196616
14196633
14196650
10
Air 0.207
LungInhale 0.481
LungExhale 0.919
AdiposeTissue 0.979
Breast 1.004
Water 1.043
Muscle 1.109
Liver 1.113
TrabecularBone 1.496
DenseBone 1.654
########################################################
# Short explanation of Data.dat #
########################################################
# 2 -> Compression Value #
# 3 -> Total number of images #
# ... -> DICM names without extension #
########################################################
########################################################
# Please do not include extension after the names #
# of the DICM images. The program will automatically #
# add <.g4> or <.dcm>. #
########################################################
+8 -1
View File
@@ -1,4 +1,4 @@
$Id: History,v 1.10 2005/12/06 14:26:35 gcosmo Exp $
$Id: History,v 1.12 2007/12/05 22:36:01 arce Exp $
-------------------------------------------------------------------
=========================================================
@@ -8,6 +8,13 @@ $Id: History,v 1.10 2005/12/06 14:26:35 gcosmo Exp $
Category History file
---------------------
06.12.2007 - Pedro Arce
Added voxel colouring by material. Added possibility to use nested parameterisation
05.12.2007 - Pedro Arce
Deep review on the input files and the way how the geometry is built.
Use of G4PhantomParameterisation and G4RegularNavigation.
06.12.2005 - Gabriele Cosmo
Trivial changes for support of CLHEP-2.0.X series.
+94 -59
View File
@@ -4,7 +4,7 @@
| README |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The DICOM application has been developed by the Geant4 users:
The DICOM application has been orignal developed by the Geant4 users:
Louis Archambault,*Luc Beaulieu, +Vincent Hubert-Tremblay.
*Centre Hospitalier Universitaire de Quebec (CHUQ),
@@ -16,89 +16,124 @@ web : thomson.phy.ulaval.ca/phys_med
+ Université Laval, Québec (QC) Canada
This example illustrates a preliminary version of a Geant4 interface
to the DICOM image format.
The example consists in creating an image from dicom files.
And it has been deeply reviewed by Pedro Arce in December 2007.
--->1) Introduction
DICOM images are read and used as Geometry for simulation.
This example serves first to convert a DICOM file to a simple ASCII file, where the Hounsfield numbers are converted to materials and densities so that it can be used by GEANT4. It serves also to create a GEANT4 geometry based on the DICOM file information using the G4PhantomParameterisation.
Three file .dcm give the experimental set-up
(in terms of tissues and tissue geometry position) are read.
It is possible to visualise the reproduced experimental
set-up thanks to the use of visualisation packages.
You can find the phantom reproduced in the image PhantomCT.jpg.
In the application the phantom is placed on a table.
In the application the phantom is placed on a table.
---> 2) Installation:
-example enviroment with the compiler 3.2.3
-a standard Geant4 example GNUmakefile is provided
setup with:
compiler = gcc-3.2.3
G4SYSTEM = linux-g++
The following environment variables need to be set:
G4LEDATA: points to low energy data base - G4EMLOW3.0
visualisation package: OpenGL
- A standard Geant4 example GNUmakefile is provided
- Compile it with 'make'
---> 3) Run the example:
- batch mode:
-dicom vis.mac :the geometry is visualised with OPENGL
-dicom run.mac :no geometry visualisation
- To run the environment variable G4LEDATA needs to be set, pointing to the low energy data base, G4EMLOW4.3
- interactive mode:
dicom
the file default.mac is read in order to visualise the phantom.
- batch mode:
- $G4INSTALL/bin/Linux-g++/dicom run.mac
--->4) Some details :
- interactive mode:
- $G4INSTALL/bin/Linux-g++/dicom
the file vis.mac is read in order to visualise the phantom with OpenGL
The DICOM images pixel values represent CT (Hounsfield) numbers and they should be
converted, first, to a given density and then to a material type. The relation between
CT number and density is more or less linear. The one used in this program is represented
in the table below.
--->4) Metadata:
The file Data.dat has the following information
- A line with the compression value (used only to create the .g4dcm, not to read it)
- A line with the number of files
- A line for each file name (to these names it will be added the suffix .dcm to read the DICOM files in their original format, and the suffix .g4dcm to read the text files that contain the DICOM information where the Hounsfield numbers have been converted to material and densities)
In case you want to convert DICOM files to text files, it must have the following lines:
- The number of materials you want to use
- A line for each material describing its name and the upper bound of the density interval. The materials should be described in increasing order of density. The voxels with a density between 0. and the first upper bound will be assigned to the first material, those with a density between the first upper bound and the second upper bound will be assigned to the second material, etc.
--->5) Conversion of Hounsfield numbers to materials:
After reading the name of files from Data.dat, if a file .dcm is found, then it looks for the corresponding .g4dcm file and if not found creates it.
Each file corresponds to a Z slice. The Z slices will be merged at runtime to form a unique patient volume; therefore the different slices have to be contiguous in Z.
The DICOM images pixel values represent CT (Hounsfield) numbers and they should be converted, first, to a given density and then to a material type. The relation between CT number and density is more or less linear.
The file CT2Density.dat contains the calibration curve to convert CT (Hounsfield) number to physical density
The assignment of material densities to materials is done following the information from the file Data.dat (see below). In this case we have used:
#####################################################
# Density Range Material #
#---------------------------------------------------#
# mg/cm3 - #
#---------------------------------------------------#
# [ 0.207 , 0.227 ] Lungs (inhale) #
# [ 0.481 , 0.534 ] Lungs (exhale) #
# [ 0.919 , 0.979 ] Adipose #
# ] 0.979 , 1.004 ] Breast #
# ] 1.004 , 1.043 ] Phantom #
# ] 1.043 , 1.109 ] Liver #
# ] 1.109 , 1.113 ] Muscle #
# ] 1.113 , 1.217 ] Trabecular Bone#
# [ 0. , 0.207 ) Air #
# [ 0.207 , 0.481 ) Lungs (inhale) #
# [ 0.481 , 0.919 ) Lungs (exhale) #
# [ 0.919 , 0.979 ) Adipose #
# [ 0.979 , 1.004 ) Breast #
# [ 1.004 , 1.043 ) Phantom #
# [ 1.043 , 1.109 ) Liver #
# [ 1.109 , 1.113 ) Muscle #
# [ 1.113 , 1.496 ) Trabecular Bone#
# [ 1.496 , 1.654 ] Dense Bone #
#####################################################
Data taken from the International Commission on Radiation Units and measurements (ICRU)
report 46 was used to build the materials (lung, liver, breast, bones, ...)
Data taken from the International Commission on Radiation Units and measurements (ICRU) report 46 was used to build the materials (lung, liver, breast, bones, ...)
5) Contacts
--->6) Splitting materials in density intervals:
If you have any questions or wish to notify of updates and/or modification
please contact:
*Louis Archambault at louis.archambault@phy.ulaval.ca
*Luc Beaulieu at beaulieu@phy.ulaval.ca
In the class DicomDetectorConstruction, it is defined a density interval
+ Vincent Hubert-Tremblay
<tigre.2@sympatico.ca> or <vihut@phy.ulaval.ca>
G4double densityDiff = 0.1;
*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
web : thomson.phy.ulaval.ca/phys_med
This means that the voxels of each material will be grouped in density intervals of 0.1 g/cm3 and a new material will be created for each group of voxels.
--->7) Voxel colouring:
The file Colormap.dat defines the colour that will be assigned to the voxels of each material.
--->8) DICOM text file format:
The DICOM files are converted to a simple text format. You may create your own file with the following format (see e.g. 14196616.g4dcm):
- A line with the number of materials
- A line for each material with its index and name (the same name of materials that you construct as G4Material's)
- A line with the number of voxels in X, Y and Z
- A line with the minimum and maximum extension in X (mm)
- A line with the minimum and maximum extension in Y (mm)
- A line with the minimum and maximum extension in Z (mm)
- A number of lines containing the nVoxelX*nVoxelY*nVoxelZ material indices (one per voxel)
- A number of lines containing the nVoxelX*nVoxelY*nVoxelZ material densities (one per voxel)
As commented before the DICOM files (.dcm) are assumed to describe one Z slice per file, and therefore the GEANT4 text files (.g4dcm) created from them have also one unique Z slice per file. Nevertheless if you create your own .g4dcm file you may include as many Z slices as desired. In any case you have to respect the rule that the Z slices must be contiguous.
--->9) Choosing different parameterisation/navigation options:
There are four possible ways in GEANT4 to treat the navigation in regular voxelised volumes:
- The non-optimised way. It will be very slow because each time a track exits a voxel it has to loop to all other voxels to know which one it may enter
- The optimisation with G4SmartVoxel: a 3D grid is built, so that the location of voxels is fast, but it requires a lot of memory
- Using G4NestedParameterisation. The search is done hierarchically in X, Y and Z. It is fast and does not require big memory
- Using G4PhantomParameterisation/G4RegularNavigation: an special algorithm to navigate in regular voxelised geometries (see GEANT4 doc). This is the fastest way without any extra memory requirement (and it is the default in this example). It includes an option (default) to skip frontiers between voxels when they have the same material
You can select amont the four options in the following way:
- By default the example will run with G4RegularNavigation
- To use the first option at RegularDicomDetectorConstruction.cc you just have to set
patient_phys->SetRegularStructureId(0);
- To use the second option apart from the change above at RegularDicomDetectorConstruction.cc you have to replace (i.e. use kUndefined)
G4PVParameterised * patient_phys = new G4PVParameterised("Patient",voxel_logic,container_logic,
kXAxis, nVoxelX*nVoxelY*nVoxelZ, param);
by
G4PVParameterised * patient_phys = new G4PVParameterised("Patient",voxel_logic,container_logic,
kUndefined, nVoxelX*nVoxelY*nVoxelZ, param);
- To use the third option you have to set the enviromental variable DICOM_NESTED_PARAM to 1
+ Université Laval, Québec (QC) Canada
@@ -1,13 +0,0 @@
/control/verbose 2
/run/verbose 2
#visualisation
/vis/scene/create
/vis/open OGLIX
/vis/drawVolume
/vis/viewer/update
/vis/viewer/zoom 5
/vis/viewer/set/viewpointThetaPhi 90 0
#/tracking/storeTrajectory 1
#/vis/scene/endOfEventAction accumulate
#/run/beamOn 1000
+12 -5
View File
@@ -51,7 +51,8 @@
#include "G4VisExecutive.hh"
#endif
#include "DicomGeometry.hh"
#include "RegularDicomDetectorConstruction.hh"
#include "NestedParamDicomDetectorConstruction.hh"
#include "DicomPrimaryGeneratorAction.hh"
#include "DicomEventAction.hh"
#include "DicomHandler.hh"
@@ -61,15 +62,21 @@ int main(int argc,char** argv)
// Treatment of DICOM images before creating the G4runManager
DicomHandler* dcmHandler = new DicomHandler;
dcmHandler->checkFileFormat();
dcmHandler->CheckFileFormat();
// Initialisation of physics, geometry, primary particles ...
G4RunManager* runManager = new G4RunManager;
DicomGeometry* theGeometry = new DicomGeometry();
DicomDetectorConstruction* theGeometry;
char* nest = getenv( "DICOM_NESTED_PARAM" );
if( nest && G4String(nest) == "1" ) {
theGeometry = new NestedParamDicomDetectorConstruction();
} else {
theGeometry = new RegularDicomDetectorConstruction();
}
runManager->SetUserInitialization(new DicomPhysicsList);
runManager->SetUserInitialization(theGeometry);
runManager->SetUserAction(new DicomPrimaryGeneratorAction());
runManager->SetUserAction(new DicomEventAction);
// runManager->SetUserAction(new DicomEventAction);
runManager->Initialize();
@@ -86,7 +93,7 @@ int main(int argc,char** argv)
if (argc==1)
{
G4UIsession* session = new G4UIterminal(new G4UItcsh);
UI->ApplyCommand("/control/execute default.mac");
UI->ApplyCommand("/control/execute vis.mac");
session->SessionStart();
delete session;
}
@@ -1,109 +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.hh :
// - Handling of the header of *.g4 files
// - Reading <Data.dat> file
#ifndef DicomConfiguration_h
#define DicomConfiguration_h 1
#include "globals.hh"
#include <vector>
class DicomConfiguration
{
public:
DicomConfiguration();
~DicomConfiguration() { }
// This function reads <Data.dat>, return true or false
// if successfull or not
G4bool ReadDataFile();
G4int GetCompressionValue() {return compressionValue;}
G4int GetTotalNumberOfFile() {return totalNumberOfFile;}
std::vector<G4String> GetListOfFile() {return listOfFile;}
G4int GetTotalRows() {return totalRows;}
G4int GetTotalColumns() {return totalColumns;}
G4int GetTotalPixels() {return totalPixels;}
//G4int GetTotalPixels() {return densityValue.size();}
G4double GetXPixelSpacing() {return xPixelSpacing;}
G4double GetYPixelSpacing() {return yPixelSpacing;}
G4double GetSliceThickness() {return sliceTickness;}
std::vector<G4double> GetSliceLocation() {return sliceLocation;}
G4int IsCompressionUsed() {return compressionUsed;}
G4double GetDensityValue(G4int i);
void ClearDensityData() {densityValue.clear(); };
G4int ReadG4File(G4String g4File);
private:
static short compressionValue;
static G4int totalNumberOfFile;
static std::vector<G4String> listOfFile;
static short totalRows;
static short totalColumns;
static G4int totalPixels;
static G4double xPixelSpacing;
static G4double yPixelSpacing;
static G4double sliceTickness;
static std::vector<G4double> sliceLocation;
static short compressionUsed;
static std::vector<G4double> densityValue;
};
#endif
@@ -0,0 +1,108 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// Author: P. Arce
// History: 30.11.07 First version
//*******************************************************
//
// DicomDetectorConstruction.hh :
// - Start the building of the geometry
// - Initialisation of materials
// - Creation of the world
// - Reading of the DICOM data
//*******************************************************
#ifndef DicomDetectorConstruction_h
#define DicomDetectorConstruction_h 1
#include "globals.hh"
#include "G4VUserDetectorConstruction.hh"
#include "DicomPatientZSliceHeader.hh"
class G4Material;
class G4Box;
class G4LogicalVolume;
class DicomDetectorConstruction : public G4VUserDetectorConstruction
{
public:
DicomDetectorConstruction();
~DicomDetectorConstruction();
G4VPhysicalVolume* Construct();
// trigger the construction of the geometry
protected:
void InitialisationOfMaterials();
// create the original materials
void ReadPatientData();
// read the DICOM files describing the patient
void ReadPatientDataFile(const G4String& fname);
// read one of the DICOM files describing the patient (usually one per Z slice). Build a DicomPatientZSliceHeader for each file
void MergeZSliceHeaders();
// merge the slice headers of all the files
G4Material* BuildMaterialWithChangingDensity( const G4Material* origMate, float density, G4String newMateName );
// build a new material if the density of the voxel is different to the other voxels
G4String ftoa(float flo);
// convert a float to a string
void ConstructPatientContainer();
virtual void ConstructPatient() = 0;
// construct the patient volumes. This method should be implemented for each of the derived classes
protected:
G4Material* air;
// World ...
G4Box* world_solid;
G4LogicalVolume* world_logic;
G4VPhysicalVolume* world_phys;
G4Box* container_solid;
G4LogicalVolume* container_logic;
G4VPhysicalVolume* container_phys;
G4int fNoFiles; // number of DICOM files
std::vector<G4Material*> fOriginalMaterials; // list of original materials
std::vector<G4Material*> fMaterials; // list of new materials created to distinguish different density voxels that have the same original materials
size_t* fMateIDs; // index of material of each voxel
std::map<G4int,G4double> fDensityDiffs; // Density difference to distinguish material for each original material (by index)
std::vector<DicomPatientZSliceHeader*> fZSliceHeaders; // list of z slice header (one per DICOM files)
DicomPatientZSliceHeader* fZSliceHeaderMerged; // z slice header resulted from merging all z slice headers
G4int nVoxelX, nVoxelY, nVoxelZ;
G4double voxelHalfDimX, voxelHalfDimY, voxelHalfDimZ;
};
#endif
@@ -1,102 +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
//*******************************************************//
//*******************************************************
//
// DicomGeometry.hh :
// - Start the building of the geometry
// - Creation of the world and other "mother"(middle) volume
// - Initialisation of patient geometry
// - Initialisation of HeaD geometry
// - Functions are in DicomGeometry.cc, PatientConstructor.cc
//*******************************************************
#ifndef DicomGeometry_h
#define DicomGeometry_h 1
#include "globals.hh"
#include "G4VUserDetectorConstruction.hh"
class DicomConfiguration;
class DicomPatientConstructor;
class G4Material;
class G4LogicalVolume;
class G4PhysicalVolume;
class G4Box;
class DicomGeometry : public G4VUserDetectorConstruction
{
public:
DicomGeometry();
~DicomGeometry();
G4VPhysicalVolume* Construct();
private:
void InitialisationOfMaterials();
void PatientConstruction();
DicomPatientConstructor* patientConstructor;
//Materials ...
G4Material* trabecularBone;
G4Material* denseBone;
G4Material* liver;
G4Material* muscle;
G4Material* phantom;
G4Material* breast;
G4Material* adiposeTissue;
G4Material* lungexhale;
G4Material* lunginhale;
G4Material* air;
// World ...
G4Box* solidWorld;
G4LogicalVolume* logicWorld;
G4VPhysicalVolume* physiWorld;
G4VPhysicalVolume* parameterisedPhysVolume;
G4VPhysicalVolume* physicalLungINhale;
};
#endif
@@ -57,6 +57,8 @@
#define DicomHandler_h 1
#include <cstdio>
#include <map>
#include <fstream>
#include "globals.hh"
@@ -68,17 +70,17 @@ public:
~DicomHandler();
G4int readHeader(FILE *,char *);
G4int readData(FILE *,char *); // note: always use readHeader
G4int ReadFile(FILE *,char *);
G4int ReadData(FILE *,char *); // note: always use readHeader
// before readData
// use ImageMagick to display the image
//G4int displayImage(char[500]);
void checkFileFormat();
void CheckFileFormat();
private:
template <class Type> void getValue(char *, Type &);
template <class Type> void GetValue(char *, Type &);
private:
@@ -86,12 +88,14 @@ private:
const int LINEBUFFSIZE;
const int FILENAMESIZE;
void storeInformation(char *);
void getInformation(G4int &, char *);
G4double pixel2density(G4int pixel);
void GetInformation(G4int &, char *);
G4double Pixel2density(G4int pixel);
void ReadMaterialIndices( std::ifstream& finData);
size_t GetMaterialIndex( G4double density );
void StoreData(std::ofstream& foutG4DCM);
short compression;
G4int max;
G4int nFiles;
short rows;
short columns;
short bitAllocated;
@@ -105,6 +109,9 @@ private:
G4bool littleEndian, implicitEndian;
short pixelRepresentation;
G4int** tab;
std::map<G4double,G4String> fMaterialIndices;
};
#endif
@@ -0,0 +1,130 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#ifndef RE02NESTEDPARAMETERISATION_HH
#define RE02NESTEDPARAMETERISATION_HH
#include "G4Types.hh"
#include "G4VNestedParameterisation.hh"
#include "G4ThreeVector.hh"
#include <vector>
class G4VPhysicalVolume;
class G4VTouchable;
class G4VSolid;
class G4Material;
// CSG Entities which may be parameterised/replicated
//
class G4Box;
class G4Tubs;
class G4Trd;
class G4Trap;
class G4Cons;
class G4Sphere;
class G4Orb;
class G4Torus;
class G4Para;
class G4Polycone;
class G4Polyhedra;
class G4Hype;
class DicomNestedPhantomParameterisation: public G4VNestedParameterisation
{
public: // with description
DicomNestedPhantomParameterisation(const G4ThreeVector& voxelSize,
std::vector<G4Material*>& mat);
virtual ~DicomNestedPhantomParameterisation();
// Methods required in derived classes
// -----------------------------------
virtual G4Material* ComputeMaterial(G4VPhysicalVolume *currentVol,
const G4int repNo,
const G4VTouchable *parentTouch=0
);
// Required method, as it is the reason for this class.
// Must cope with parentTouch=0 for navigator's SetupHierarchy
virtual G4int GetNumberOfMaterials() const;
virtual G4Material* GetMaterial(G4int idx) const;
// Needed to define materials for instances of Nested Parameterisation
// Current convention: each call should return the materials
// of all instances with the same mother/ancestor volume.
size_t GetMaterialIndex( size_t nx, size_t ny, size_t nz) const;
size_t GetMaterialIndex( size_t copyNo) const;
void SetMaterialIndices( size_t* matInd ){
fMaterialIndices = matInd; }
void SetNoVoxel( size_t nx, size_t ny, size_t nz );
virtual void ComputeTransformation(const G4int no,
G4VPhysicalVolume *currentPV) const;
// Methods optional in derived classes
// -----------------------------------
// Additional standard Parameterisation methods,
// which can be optionally defined, in case solid is used.
virtual void ComputeDimensions(G4Box &,
const G4int,
const G4VPhysicalVolume *) const;
private: // Dummy declarations to get rid of warnings ...
void ComputeDimensions (G4Trd&,const G4int,const G4VPhysicalVolume*)
const {}
void ComputeDimensions (G4Trap&,const G4int,const G4VPhysicalVolume*)
const {}
void ComputeDimensions (G4Cons&,const G4int,const G4VPhysicalVolume*)
const {}
void ComputeDimensions (G4Sphere&,const G4int,const G4VPhysicalVolume*)
const {}
void ComputeDimensions (G4Orb&,const G4int,const G4VPhysicalVolume*)
const {}
void ComputeDimensions (G4Torus&,const G4int,const G4VPhysicalVolume*)
const {}
void ComputeDimensions (G4Para&,const G4int,const G4VPhysicalVolume*)
const {}
void ComputeDimensions (G4Hype&,const G4int,const G4VPhysicalVolume*)
const {}
void ComputeDimensions (G4Tubs&,const G4int,const G4VPhysicalVolume*)
const {}
void ComputeDimensions (G4Polycone&,const G4int,const G4VPhysicalVolume*)
const {}
void ComputeDimensions (G4Polyhedra&,const G4int,const G4VPhysicalVolume*)
const {}
private:
G4double fdX,fdY,fdZ;
G4int fnX,fnY,fnZ;
//
std::vector<G4Material*> fMaterials;
size_t* fMaterialIndices;
// Index in fMaterials that correspond to each voxel.
};
#endif
@@ -1,100 +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
//*******************************************************//
//
//---------------------------------------------------------------------------
/// Octree encapsulates a volumetric compressed representation of the
/// vector field used for the reconstruction of a 3D model from multiple
/// range images or curves.
///
/// It is assumed that the space occupied by octree is a cube whose
/// bottom-left-front corner is at origin (0,0,0) while the opposite corner
/// (top,right,back) is at ( mSize,mSize,mSize). Resolution of an octree
/// denotes the number of voxels along each axis such
/// that the resolution = 2^mNoLevels.
// -------------------------------------------------------------------------
#ifndef DICOMOCTREE_HH
#define DICOMOCTREE_HH
#include "globals.hh"
#include "DicomOctreeNode.hh"
#include "DicomOctreeMiddleNode.hh"
#include "DicomOctreeTerminalNode.hh"
class DicomOctreeNode;
class DicomOctreeMiddleNode;
class DicomTerminalNode;
class DicomOctree;
class DicomOctree
{
public:
DicomOctree( G4int noLevels, G4double size );
~DicomOctree();
DicomOctreeNode* CreateNode( G4double i, G4double j, G4double k, G4int level );
DicomOctreeNode* operator()( G4double nodeX, G4double nodeY,
G4double nodeZ, G4int level );
void DeleteTree();
G4int CountMemory( G4int rMiddle, G4int rTerminal );
DicomOctreeNode* Root() { return mRoot; }
G4double Size() { return mSize; }
G4int NoLevels() { return mNoLevels; }
//G4bool Resolution() { return ( 1 << mNoLevels ); }
G4int GetIndexChild() { return indexChild;}
private:
void CountRecursive( DicomOctreeNode* pNode, G4int rMiddle, G4int rTerminal );
// Root node of the tree
DicomOctreeMiddleNode* mRoot;
// In an octree, size denotes physical size of the cube,
// ie length of its sides (which are assumed equal).
G4double mSize;
// Number of levels denotes the maximal number of
// nodes in a single branch, starting from the root node.
G4int mNoLevels;
G4int indexChild;
};
#endif
@@ -1,63 +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
//*******************************************************//
#ifndef DicomOctreeMiddleNode_h
#define DicomOctreeMiddleNode_h
#include "globals.hh"
class DicomOctree;
class DicomOctreeMiddleNode : public DicomOctreeNode
{
public:
DicomOctreeMiddleNode();
~DicomOctreeMiddleNode();
public:
void ResetFamily();
DicomOctreeMiddleNode( DicomOctreeNode* pParent );
G4int FindChild( const DicomOctreeNode* pNode );
G4int MemSize();
DicomOctreeNode*& operator []( G4int index ) {return mChildren[index];}
OctreeNodeType Type() {return MIDDLE_NODE;}
private:
DicomOctreeNode* mChildren[8];
DicomOctree* octree;
};
#endif
@@ -1,75 +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
//*******************************************************//
#ifndef DICOMOCTREENODE_H
#define DICOMOCTREENODE_H
#include "globals.hh"
enum OctreeNodeType { MIDDLE_NODE, TERMINAL_NODE };
// OctreeNode represents a single node in the Octree.
class DicomOctreeNode
{
public:
DicomOctreeNode();
~DicomOctreeNode();
DicomOctreeNode( DicomOctreeNode* pParent );
G4double Density(){return mDensity;}
virtual DicomOctreeNode*& operator []( G4int index ) = 0;
virtual OctreeNodeType Type() = 0;
const DicomOctreeNode* Parent(){ return mParent; }
virtual G4int FindChild( const DicomOctreeNode* pNode ) = 0;
static G4int InstanceCounter() { return mInstanceCounter; }
virtual G4int MemSize() = 0;
private:
static G4int mInstanceCounter;
DicomOctreeNode* mParent;
G4double mDensity;
};
#endif
@@ -1,67 +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
//*******************************************************//
#ifndef DicomPatientConstructor_h
#define DicomPatientConstructor_h 1
#include "globals.hh"
class DicomPatientConstructor
{
public:
DicomPatientConstructor() {;}
~DicomPatientConstructor() {;}
G4int FindingNbOfVoxels(G4double maxDensity, G4double minDensity);
// Functions to use ROI (region of interest), contour usually drawn by the
// physician to identify tumor volume and organ at risk
// under development ...
// void readContour();
//G4bool isWithin(G4double,G4double,G4double);
private:
G4double pixelSpacingX;
G4double pixelSpacingY;
G4double sliceThickness;
G4double sliceLocation;
G4int lenc,lenr;
};
#endif
@@ -1,189 +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
//*******************************************************//
#ifndef DicomPatientParameterisation_h
#define DicomPatientParameterisation_h 1
#include "globals.hh"
#include "G4VPVParameterisation.hh"
#include <vector>
class G4VPhysicalVolume;
class G4LogicalVolume;
class G4Box;
class G4Material;
class G4VisAttributes;
class DicomConfiguration;
class DicomPatientParameterisation : public G4VPVParameterisation
{
public:
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);
virtual ~DicomPatientParameterisation();
void ComputeTransformation (const G4int copyNo, G4VPhysicalVolume* physVol) const;
void ComputeDimensions(G4Box&,
const G4int,
const G4VPhysicalVolume* ) const;
void ComputeDimensions(G4Tubs &,
const G4int,
const G4VPhysicalVolume *) const {}
void ComputeDimensions(G4Trd &,
const G4int,
const G4VPhysicalVolume *) const {}
void ComputeDimensions(G4Trap &,
const G4int,
const G4VPhysicalVolume *) const {}
void ComputeDimensions(G4Cons &,
const G4int,
const G4VPhysicalVolume *) const {}
void ComputeDimensions(G4Sphere &,
const G4int,
const G4VPhysicalVolume *) const {}
void ComputeDimensions(G4Orb &,
const G4int,
const G4VPhysicalVolume *) const {}
void ComputeDimensions(G4Torus &,
const G4int,
const G4VPhysicalVolume *) const {}
void ComputeDimensions(G4Para &,
const G4int,
const G4VPhysicalVolume *) const {}
void ComputeDimensions(G4Polycone &,
const G4int,
const G4VPhysicalVolume *) const {}
void ComputeDimensions(G4Polyhedra &,
const G4int,
const G4VPhysicalVolume *) const {}
void ComputeDimensions(G4Hype &,
const G4int,
const G4VPhysicalVolume *) const {}
G4Material* ComputeMaterial(const G4int copyNo,
G4VPhysicalVolume* physVol,
const G4VTouchable*);
void GetDensity( G4double maxDensity, G4double minDensity );
private:
//materials ...
G4Material* lungExhale;
G4Material* lungInhale;
G4Material* adiposeTissue;
G4Material* breastTissue;
G4Material* phantomTissue;
G4Material* muscleTissue;
G4Material* liverTissue;
G4Material* denseBoneTissue;
G4Material* trabecularBoneTissue;
G4VisAttributes* attributeAir;
G4VisAttributes* attributeLungINhale;
G4VisAttributes* attributeLungEXhale;
G4VisAttributes* attributeAdipose;
G4VisAttributes* attributeBreast;
G4VisAttributes* attributePhantom;
G4VisAttributes* attributeMuscle;
G4VisAttributes* attributeLiver;
G4VisAttributes* attributeTrabecularBone;
G4VisAttributes* attributeDenseBone;
G4int max;
short compression;
FILE* readData;
short columns,rows;
G4double pixelSpacingX;
G4double pixelSpacingY;
G4double sliceThickness;
G4double sliceLocation;
std::vector<G4double> density;
std::vector<G4double> patientPlacementX;
std::vector<G4double> patientPlacementY;
std::vector<G4double> patientPlacementZ;
//G4LogicalVolume* LogicalVolumeParam;
G4double middleLocationValue;
private:
void readColorChart();
class ColorChart {
public:
G4double density;
G4double color[3];
G4double alpha;
enum {CRED, CGREEN, CBLUE};
};
std::vector<ColorChart> colorChart;
G4int numColorChart;
G4double getChartColor(G4int, G4double density);
};
#endif
@@ -0,0 +1,106 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// Author: P. Arce
// History: 30.11.07 First version
//*******************************************************
//
// DicomPatientZSliceHeader.hh :
// - Contains the meta data information corresponding to one or several Z slices (number of voxels, dimension)
//*******************************************************
#ifndef DicomPatientZSliceHeader_h
#define DicomPatientZSliceHeader_h 1
#include "globals.hh"
class G4material;
#include <fstream>
#include <vector>
class DicomPatientZSliceHeader
{
public:
DicomPatientZSliceHeader( const DicomPatientZSliceHeader& rhs );
// build object copying an existing one (except Z dimensions)
DicomPatientZSliceHeader( std::ifstream& fin );
// build object reading data from a file
~DicomPatientZSliceHeader(){};
// Get and set methods
G4int GetNoVoxelX() const { return fNoVoxelX; };
G4int GetNoVoxelY() const { return fNoVoxelY; };
G4int GetNoVoxelZ() const { return fNoVoxelZ; };
G4int GetNoVoxels() const { return fNoVoxelX*fNoVoxelY*fNoVoxelZ; };
G4double GetMinX() const { return fMinX; };
G4double GetMinY() const { return fMinY; };
G4double GetMinZ() const { return fMinZ; };
G4double GetMaxX() const { return fMaxX; };
G4double GetMaxY() const { return fMaxY; };
G4double GetMaxZ() const { return fMaxZ; };
G4double GetVoxelHalfX() const { return (fMaxX-fMinX)/fNoVoxelX/2.; };
G4double GetVoxelHalfY() const { return (fMaxY-fMinY)/fNoVoxelY/2.; };
G4double GetVoxelHalfZ() const { return (fMaxZ-fMinZ)/fNoVoxelZ/2.; };
std::vector<G4String> GetMaterialNames() const { return fMaterialNames; };
void SetNoVoxelX(const G4int val) { fNoVoxelX = val; }
void SetNoVoxelY(const G4int val) { fNoVoxelY = val; }
void SetNoVoxelZ(const G4int val) { fNoVoxelZ = val; }
void SetMinX(const G4double val) { fMinX = val; };
void SetMaxX(const G4double val) { fMaxX = val; };
void SetMinY(const G4double val) { fMinY = val; };
void SetMaxY(const G4double val) { fMaxY = val; };
void SetMinZ(const G4double val) { fMinZ = val; };
void SetMaxZ(const G4double val) { fMaxZ = val; };
void SetMaterialNames(std::vector<G4String>& mn ){ fMaterialNames = mn; }
void operator+=( const DicomPatientZSliceHeader& rhs );
DicomPatientZSliceHeader operator+( const DicomPatientZSliceHeader& rhs );
// add two slices that have the same dimensions, merging them in Z
private:
G4bool CheckMaterialExists( const G4String& mateName );
// check that material read exists as a G4Material
private:
G4int fNoVoxelX, fNoVoxelY, fNoVoxelZ; // number of voxels in each dimensions
G4double fMinX,fMinY,fMinZ; // minimum extension of voxels (position of wall)
G4double fMaxX,fMaxY,fMaxZ; // maximum extension of voxels (position of wall)
std::vector<G4String> fMaterialNames; // list of material names
};
#endif
@@ -23,38 +23,40 @@
// * 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
// class DicomPhantomParameterisationColour
//
//
// *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
//*******************************************************//
#ifndef DicomOctreeTerminalNode_h
#define DicomOctreeTerminalNode_h
// Class description:
//
// Class inherited from G4PhantomParameterisation to provide different colour for each material
// History:
// - Created. P. Arce, 5 December 2007
// *********************************************************************
class DicomOctreeTerminalNode : public DicomOctreeNode
#ifndef DicomPhantomParameterisationColour_HH
#define DicomPhantomParameterisationColour_HH
#include <map>
#include "G4PhantomParameterisation.hh"
class G4VisAttributes;
class DicomPhantomParameterisationColour : public G4PhantomParameterisation
{
public:
DicomOctreeTerminalNode(DicomOctreeNode* pParent );
~ DicomOctreeTerminalNode();
public:
// ---- MGP ---- Replace *& with proper design of the operator
DicomOctreeNode*& operator []( G4int index );
G4int MemSize();
OctreeNodeType Type() {return TERMINAL_NODE;}
G4int FindChild( const DicomOctreeNode* ) {return -1;}
public: // with description
DicomPhantomParameterisationColour();
~DicomPhantomParameterisationColour();
virtual G4Material* ComputeMaterial(const G4int repNo,
G4VPhysicalVolume *currentVol,
const G4VTouchable *parentTouch=0);
private:
void ReadColourData();
private:
static DicomOctreeNode* mNull;
std::map<G4String,G4VisAttributes*> fColours;
};
#endif
@@ -36,6 +36,9 @@
// fax (418) 691 5268
//
// + Université Laval, Québec (QC) Canada
//
// History: 30.11.07 P.Arce modified so that some particles reach patient voxels
//
//*******************************************************
#ifndef DicomPrimaryGeneratorAction_h
@@ -23,40 +23,32 @@
// * 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
// Author: P. Arce
// History: 30.11.07 First version
//*******************************************************
//
//
// *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
// NestedParamDicomDetectorConstruction.hh :
// - Construct the patient using DicomPhantomParameterisationColour
//*******************************************************
#include <stddef.h>
#include "DicomOctreeNode.hh"
#ifndef NestedParamDicomDetectorConstruction_h
#define NestedParamDicomDetectorConstruction_h 1
G4int DicomOctreeNode::mInstanceCounter = 0;
#include "globals.hh"
#include "DicomDetectorConstruction.hh"
DicomOctreeNode::DicomOctreeNode()
class NestedParamDicomDetectorConstruction : public DicomDetectorConstruction
{
mParent = 0;
mInstanceCounter++;
}
public:
DicomOctreeNode::~DicomOctreeNode()
{
mInstanceCounter--;
}
NestedParamDicomDetectorConstruction();
~NestedParamDicomDetectorConstruction();
DicomOctreeNode::DicomOctreeNode( DicomOctreeNode* pParent )
{
mParent = pParent;
mInstanceCounter++;
}
private:
virtual void ConstructPatient();
};
#endif
@@ -23,44 +23,32 @@
// * 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
// Author: P. Arce
// History: 30.11.07 First version
//*******************************************************
//
//
// *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
// RegularDicomDetectorConstruction.hh :
// - Construct the patient using DicomPhantomParameterisationColour
//*******************************************************
#ifndef RegularDicomDetectorConstruction_h
#define RegularDicomDetectorConstruction_h 1
#include "DicomOctreeNode.hh"
#include "DicomOctreeTerminalNode.hh"
#include "globals.hh"
#include "DicomDetectorConstruction.hh"
DicomOctreeNode* DicomOctreeTerminalNode::mNull = 0;
DicomOctreeTerminalNode::DicomOctreeTerminalNode( DicomOctreeNode* pParent) : DicomOctreeNode( pParent )
class RegularDicomDetectorConstruction : public DicomDetectorConstruction
{
public:
}
DicomOctreeTerminalNode::~DicomOctreeTerminalNode()
{
RegularDicomDetectorConstruction();
~RegularDicomDetectorConstruction();
}
private:
DicomOctreeNode*& DicomOctreeTerminalNode::operator []( G4int )
{
return mNull;
}
virtual void ConstructPatient();
G4int DicomOctreeTerminalNode::MemSize()
{
return sizeof(DicomOctreeTerminalNode);
}
};
#endif
+5 -1
View File
@@ -1,3 +1,7 @@
/control/verbose 1
/run/verbose 1
/run/beamOn 10
/tracking/verbose 1
/random/setDirectoryName .
/random/setSavingFlag 1
#/random/resetEngineFrom currentEvent.rndm1
/run/beamOn 100
@@ -1,149 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// The code was written by :
// *Louis Archambault louis.archambault@phy.ulaval.ca,
// *Luc Beaulieu beaulieu@phy.ulaval.ca
// +Vincent Hubert-Tremblay at tigre.2@sympatico.ca
//
//
// *Centre Hospitalier Universitaire de Quebec (CHUQ),
// Hotel-Dieu de Quebec, departement de Radio-oncologie
// 11 cote du palais. Quebec, QC, Canada, G1R 2J6
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Université Laval, Québec (QC) Canada
//*******************************************************
//
//
// DicomConfiguration.cc :
// - Handling of the header of *.g4 files
// - Reading <Data.dat> file
#include "globals.hh"
#include "DicomConfiguration.hh"
#include <fstream>
#include <vector>
short DicomConfiguration::compressionValue = 0;
G4int DicomConfiguration::totalNumberOfFile = 0;
std::vector<G4String> DicomConfiguration::listOfFile;
short DicomConfiguration::totalRows = 0;
short DicomConfiguration::totalColumns = 0;
G4int DicomConfiguration::totalPixels = 0;
G4double DicomConfiguration::xPixelSpacing = 0.;
G4double DicomConfiguration::yPixelSpacing = 0.;
G4double DicomConfiguration::sliceTickness = 0.;
std::vector<G4double> DicomConfiguration::sliceLocation;
short DicomConfiguration::compressionUsed = 0;
std::vector<G4double> DicomConfiguration::densityValue;
//
DicomConfiguration::DicomConfiguration() {
ReadDataFile();
}
//
G4bool DicomConfiguration::ReadDataFile() {
if(totalNumberOfFile > 0) return true;
totalPixels = 0;
std::ifstream dataFile("Data.dat");
G4String nameOfFileBuffer;
if(dataFile.good() != 1 ) return 1;
dataFile >> compressionValue;
dataFile >> totalNumberOfFile;
for(G4int i = 0; i < totalNumberOfFile; i++ ) {
dataFile >> nameOfFileBuffer;
listOfFile.push_back( nameOfFileBuffer );
// read densities from .g4 file
ReadG4File(nameOfFileBuffer);
}
dataFile.close();
return 0;
}
G4int DicomConfiguration::ReadG4File( G4String g4File ) {
//densityValue.clear();
g4File = g4File + ".g4";
std::ifstream readingG4FileHeader(g4File.c_str(),
std::ios_base::in | std::ios_base::binary);
if ( readingG4FileHeader.good() != 1 ) return 1;
readingG4FileHeader.read((char *)&totalRows, 2);
readingG4FileHeader.read((char *)&totalColumns, 2);
readingG4FileHeader.read((char *)&xPixelSpacing, 8);
readingG4FileHeader.read((char *)&yPixelSpacing, 8);
readingG4FileHeader.read((char *)&sliceTickness, 8);
G4double sliceLocationBuff;
readingG4FileHeader.read((char *)&sliceLocationBuff, 8);
readingG4FileHeader.read((char *)&compressionUsed, 2);
sliceLocation.push_back(sliceLocationBuff);
G4double density;
for(int y = 0; y < totalRows/compressionUsed; y++) {
for(int x = 0; x < totalColumns/compressionUsed; x++) {
readingG4FileHeader.read((char *)&density, sizeof(G4double));
densityValue.push_back(density);
totalPixels++;
}
}
readingG4FileHeader.close();
return 0;
}
G4double DicomConfiguration::GetDensityValue(G4int i) {
G4double value = 0.;
if (i >= 0) {
unsigned int j = i;
//
if(j > densityValue.size() ) {
// Throw exception, return dummy, cerr error message...
G4cout << "out of range in GetDensityValue()! : "
<< j << ", " << totalPixels << G4endl;
} else {
value = densityValue[i];
}
} else {
G4cout << "out of range in GetDensityValue()!"<<G4endl;
}
return value;
}
@@ -0,0 +1,452 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
#include "globals.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4VPhysicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "DicomDetectorConstruction.hh"
#include "DicomPatientZSliceHeader.hh"
//-------------------------------------------------------------
DicomDetectorConstruction::DicomDetectorConstruction()
{
}
//-------------------------------------------------------------
DicomDetectorConstruction::~DicomDetectorConstruction()
{
}
//-------------------------------------------------------------
G4VPhysicalVolume* DicomDetectorConstruction::Construct()
{
InitialisationOfMaterials();
//----- Build world
G4double worldXDimension = 1.*m;
G4double worldYDimension = 1.*m;
G4double worldZDimension = 1.*m;
world_solid = new G4Box( "WorldSolid",
worldXDimension,
worldYDimension,
worldZDimension );
world_logic = new G4LogicalVolume( world_solid,
air,
"WorldLogical",
0, 0, 0 );
world_phys = new G4PVPlacement( 0,
G4ThreeVector(0,0,0),
"World",
world_logic,
0,
false,
0 );
ReadPatientData();
ConstructPatientContainer();
ConstructPatient();
return world_phys;
}
//-------------------------------------------------------------
void DicomDetectorConstruction::InitialisationOfMaterials()
{
// Creating elements :
G4double z, a, density;
G4String name, symbol;
G4Element* elC = new G4Element( name = "Carbon",
symbol = "C",
z = 6.0, a = 12.011 * g/mole );
G4Element* elH = new G4Element( name = "Hydrogen",
symbol = "H",
z = 1.0, a = 1.008 * g/mole );
G4Element* elN = new G4Element( name = "Nitrogen",
symbol = "N",
z = 7.0, a = 14.007 * g/mole );
G4Element* elO = new G4Element( name = "Oxygen",
symbol = "O",
z = 8.0, a = 16.00 * g/mole );
G4Element* elNa = new G4Element( name = "Sodium",
symbol = "Na",
z= 11.0, a = 22.98977* g/mole );
G4Element* elS = new G4Element( name = "Sulfur",
symbol = "S",
z = 16.0,a = 32.065* g/mole );
G4Element* elCl = new G4Element( name = "Chlorine",
symbol = "P",
z = 17.0, a = 35.453* g/mole );
G4Element* elK = new G4Element( name = "Potassium",
symbol = "P",
z = 19.0, a = 30.0983* g/mole );
G4Element* elP = new G4Element( name = "Phosphorus",
symbol = "P",
z = 30.0, a = 30.973976* g/mole );
G4Element* elFe = new G4Element( name = "Iron",
symbol = "Fe",
z = 26, a = 56.845* g/mole );
G4Element* elMg = new G4Element( name = "Magnesium",
symbol = "Mg",
z = 12.0, a = 24.3050* g/mole );
G4Element* elCa = new G4Element( name="Calcium",
symbol = "Ca",
z = 20.0, a = 40.078* g/mole );
// Creating Materials :
G4int numberofElements;
// Air
air = new G4Material( "Air",
1.290*mg/cm3,
numberofElements = 2 );
air->AddElement(elN, 0.7);
air->AddElement(elO, 0.3);
// Lung Inhale
G4Material* lunginhale = new G4Material( "LungInhale",
density = 0.217*g/cm3,
numberofElements = 9);
lunginhale->AddElement(elH,0.103);
lunginhale->AddElement(elC,0.105);
lunginhale->AddElement(elN,0.031);
lunginhale->AddElement(elO,0.749);
lunginhale->AddElement(elNa,0.002);
lunginhale->AddElement(elP,0.002);
lunginhale->AddElement(elS,0.003);
lunginhale->AddElement(elCl,0.002);
lunginhale->AddElement(elK,0.003);
// Lung exhale
G4Material* lungexhale = new G4Material( "LungExhale",
density = 0.508*g/cm3,
numberofElements = 9 );
lungexhale->AddElement(elH,0.103);
lungexhale->AddElement(elC,0.105);
lungexhale->AddElement(elN,0.031);
lungexhale->AddElement(elO,0.749);
lungexhale->AddElement(elNa,0.002);
lungexhale->AddElement(elP,0.002);
lungexhale->AddElement(elS,0.003);
lungexhale->AddElement(elCl,0.002);
lungexhale->AddElement(elK,0.003);
// Adipose tissue
G4Material* adiposeTissue = new G4Material( "AdiposeTissue",
density = 0.967*g/cm3,
numberofElements = 7);
adiposeTissue->AddElement(elH,0.114);
adiposeTissue->AddElement(elC,0.598);
adiposeTissue->AddElement(elN,0.007);
adiposeTissue->AddElement(elO,0.278);
adiposeTissue->AddElement(elNa,0.001);
adiposeTissue->AddElement(elS,0.001);
adiposeTissue->AddElement(elCl,0.001);
// Breast
G4Material* breast = new G4Material( "Breast",
density = 0.990*g/cm3,
numberofElements = 8 );
breast->AddElement(elH,0.109);
breast->AddElement(elC,0.506);
breast->AddElement(elN,0.023);
breast->AddElement(elO,0.358);
breast->AddElement(elNa,0.001);
breast->AddElement(elP,0.001);
breast->AddElement(elS,0.001);
breast->AddElement(elCl,0.001);
// Water
G4Material* water = new G4Material( "Water",
density = 1.0*g/cm3,
numberofElements = 2 );
water->AddElement(elH,0.112);
water->AddElement(elO,0.888);
// Muscle
G4Material* muscle = new G4Material( "Muscle",
density = 1.061*g/cm3,
numberofElements = 9 );
muscle->AddElement(elH,0.102);
muscle->AddElement(elC,0.143);
muscle->AddElement(elN,0.034);
muscle->AddElement(elO,0.710);
muscle->AddElement(elNa,0.001);
muscle->AddElement(elP,0.002);
muscle->AddElement(elS,0.003);
muscle->AddElement(elCl,0.001);
muscle->AddElement(elK,0.004);
// Liver
G4Material* liver = new G4Material( "Liver",
density = 1.071*g/cm3,
numberofElements = 9);
liver->AddElement(elH,0.102);
liver->AddElement(elC,0.139);
liver->AddElement(elN,0.030);
liver->AddElement(elO,0.716);
liver->AddElement(elNa,0.002);
liver->AddElement(elP,0.003);
liver->AddElement(elS,0.003);
liver->AddElement(elCl,0.002);
liver->AddElement(elK,0.003);
// Trabecular Bone
G4Material* trabecularBone = new G4Material( "TrabecularBone",
density = 1.159*g/cm3,
numberofElements = 12 );
trabecularBone->AddElement(elH,0.085);
trabecularBone->AddElement(elC,0.404);
trabecularBone->AddElement(elN,0.058);
trabecularBone->AddElement(elO,0.367);
trabecularBone->AddElement(elNa,0.001);
trabecularBone->AddElement(elMg,0.001);
trabecularBone->AddElement(elP,0.034);
trabecularBone->AddElement(elS,0.002);
trabecularBone->AddElement(elCl,0.002);
trabecularBone->AddElement(elK,0.001);
trabecularBone->AddElement(elCa,0.044);
trabecularBone->AddElement(elFe,0.001);
// Dense Bone
G4Material* denseBone = new G4Material( "DenseBone",
density = 1.575*g/cm3,
numberofElements = 11 );
denseBone->AddElement(elH,0.056);
denseBone->AddElement(elC,0.235);
denseBone->AddElement(elN,0.050);
denseBone->AddElement(elO,0.434);
denseBone->AddElement(elNa,0.001);
denseBone->AddElement(elMg,0.001);
denseBone->AddElement(elP,0.072);
denseBone->AddElement(elS,0.003);
denseBone->AddElement(elCl,0.001);
denseBone->AddElement(elK,0.001);
denseBone->AddElement(elCa,0.146);
//----- Put the materials in a vector
fOriginalMaterials.push_back(air); // rho = 0.00129
fOriginalMaterials.push_back(lunginhale); // rho = 0.217
fOriginalMaterials.push_back(lungexhale); // rho = 0.508
fOriginalMaterials.push_back(adiposeTissue); // rho = 0.967
fOriginalMaterials.push_back(breast ); // rho = 0.990
fOriginalMaterials.push_back(water); // rho = 1.018
fOriginalMaterials.push_back(muscle); // rho = 1.061
fOriginalMaterials.push_back(liver); // rho = 1.071
fOriginalMaterials.push_back(trabecularBone); // rho = 1.159
fOriginalMaterials.push_back(denseBone); // rho = 1.575
}
//-------------------------------------------------------------
void DicomDetectorConstruction::ReadPatientData()
{
std::ifstream finDF("Data.dat");
G4String fname;
if(finDF.good() != 1 ) {
G4Exception(" DicomDetectorConstruction::ReadPatientData. Problem reading data file: Data.dat");
}
G4int compression;
finDF >> compression; // not used here
finDF >> fNoFiles;
for(G4int i = 0; i < fNoFiles; i++ ) {
finDF >> fname;
//--- Read one data file
fname += ".g4dcm";
ReadPatientDataFile(fname);
}
//----- Merge data headers
MergeZSliceHeaders();
finDF.close();
}
//-------------------------------------------------------------
void DicomDetectorConstruction::ReadPatientDataFile(const G4String& fname)
{
#ifdef G4VERBOSE
G4cout << " DicomDetectorConstruction::ReadPatientDataFile opening file " << fname << G4endl;
#endif
std::ifstream fin(fname.c_str(), std::ios_base::in);
if( !fin.is_open() ) {
G4Exception("DicomDetectorConstruction::ReadPatientDataFil. File not found " + fname );
}
//----- Define density differences (maximum density difference to create a new material)
G4double densityDiff = 0.1;
std::map<G4int,G4double> fDensityDiffs; // to be able to use a different densityDiff for each material
for( size_t ii = 0; ii < fOriginalMaterials.size(); ii++ ){
fDensityDiffs[ii] = densityDiff; //currently all materials with same difference
}
//----- Read data header
DicomPatientZSliceHeader* sliceHeader = new DicomPatientZSliceHeader( fin );
fZSliceHeaders.push_back( sliceHeader );
//----- Read material indices
G4int nVoxels = sliceHeader->GetNoVoxels();
//--- If first slice, initiliaze fMateIDs
if( fZSliceHeaders.size() == 1 ) {
fMateIDs = new size_t[fNoFiles*nVoxels];
}
size_t mateID;
G4int voxelCopyNo = (fZSliceHeaders.size()-1)*nVoxels; // number of voxels from previously read slices
for( G4int ii = 0; ii < nVoxels; ii++, voxelCopyNo++ ){
fin >> mateID;
fMateIDs[voxelCopyNo] = mateID;
}
//----- Read material densities and build new materials if two voxels have same material but its density is in a different density interval (size of density intervals defined by densityDiff)
G4double density;
voxelCopyNo = (fZSliceHeaders.size()-1)*nVoxels; // number of voxels from previously read slices
for( G4int ii = 0; ii < nVoxels; ii++, voxelCopyNo++ ){
fin >> density;
//-- Get material from list of original materials
int mateID = fMateIDs[voxelCopyNo];
G4Material* mateOrig = fOriginalMaterials[mateID];
//-- Get density bin: middle point of the bin in which the current density is included
float densityBin = fDensityDiffs[mateID] * (G4int(density/fDensityDiffs[mateID])+0.5);
//-- Build the new material name
G4String newMateName = mateOrig->GetName()+"__"+ftoa(densityBin);
//-- Look if a material with this name is already created (because a previous voxel was already in this density bin)
size_t im;
for( im = 0; im < fMaterials.size(); im++ ){
if( fMaterials[im]->GetName() == newMateName ) {
break;
}
}
//-- If material is already created use index of this material
if( im != fMaterials.size() ) {
fMateIDs[voxelCopyNo] = im;
//-- else, create the material
} else {
fMaterials.push_back( BuildMaterialWithChangingDensity( mateOrig, densityBin, newMateName ) );
fMateIDs[voxelCopyNo] = fMaterials.size()-1;
}
}
}
//-------------------------------------------------------------
void DicomDetectorConstruction::MergeZSliceHeaders()
{
//----- Images must have the same dimension ...
fZSliceHeaderMerged = new DicomPatientZSliceHeader( *fZSliceHeaders[0] );
for( size_t ii = 1; ii < fZSliceHeaders.size(); ii++ ) {
*fZSliceHeaderMerged += *fZSliceHeaders[ii];
};
}
//-------------------------------------------------------------
G4Material* DicomDetectorConstruction::BuildMaterialWithChangingDensity( const G4Material* origMate, float density, G4String newMateName )
{
//----- Copy original material, but with new density
G4int nelem = origMate->GetNumberOfElements();
G4Material* mate = new G4Material( newMateName, density*g/cm3, nelem, kStateUndefined, STP_Temperature );
for( G4int ii = 0; ii < nelem; ii++ ){
G4double frac = origMate->GetFractionVector()[ii];
G4Element* elem = const_cast<G4Element*>(origMate->GetElement(ii));
mate->AddElement( elem, frac );
}
return mate;
}
//-----------------------------------------------------------------------
G4String DicomDetectorConstruction::ftoa(float flo)
{
char ctmp[100];
gcvt( flo, 10, ctmp );
return G4String(ctmp);
}
//-------------------------------------------------------------
void DicomDetectorConstruction::ConstructPatientContainer()
{
//---- Extract number of voxels and voxel dimensions
nVoxelX = fZSliceHeaderMerged->GetNoVoxelX();
nVoxelY = fZSliceHeaderMerged->GetNoVoxelY();
nVoxelZ = fZSliceHeaderMerged->GetNoVoxelZ();
voxelHalfDimX = fZSliceHeaderMerged->GetVoxelHalfX();
voxelHalfDimY = fZSliceHeaderMerged->GetVoxelHalfY();
voxelHalfDimZ = fZSliceHeaderMerged->GetVoxelHalfZ();
#ifdef G4VERBOSE
G4cout << " nVoxelX " << nVoxelX << " voxelHalfDimX " << voxelHalfDimX <<G4endl;
G4cout << " nVoxelY " << nVoxelY << " voxelHalfDimY " << voxelHalfDimY <<G4endl;
G4cout << " nVoxelZ " << nVoxelZ << " voxelHalfDimZ " << voxelHalfDimZ <<G4endl;
G4cout << " totalPixels " << nVoxelX*nVoxelY*nVoxelZ << G4endl;
#endif
//----- Define the volume that contains all the voxels
container_solid = new G4Box("PhantomContainer",nVoxelX*voxelHalfDimX,nVoxelY*voxelHalfDimY,nVoxelZ*voxelHalfDimZ);
container_logic =
new G4LogicalVolume( container_solid,
fMaterials[0], //the material is not important, it will be fully filled by the voxels
"PhantomContainer",
0, 0, 0 );
//--- Place it on the world
G4double offsetX = (fZSliceHeaderMerged->GetMaxX() + fZSliceHeaderMerged->GetMinX() ) /2.;
G4double offsetY = (fZSliceHeaderMerged->GetMaxY() + fZSliceHeaderMerged->GetMinY() ) /2.;
G4double offsetZ = (fZSliceHeaderMerged->GetMaxZ() + fZSliceHeaderMerged->GetMinZ() ) /2.;
G4ThreeVector posCentreVoxels(offsetX,offsetY,offsetZ);
#ifdef G4VERBOSE
G4cout << " placing voxel container volume at " << posCentreVoxels << G4endl;
#endif
container_phys =
new G4PVPlacement(0, // rotation
posCentreVoxels,
container_logic, // The logic volume
"PhantomContainer", // Name
world_logic, // Mother
false, // No op. bool.
1); // Copy number
}
@@ -51,8 +51,10 @@ DicomEventAction::DicomEventAction():drawFlag("all")
DicomEventAction::~DicomEventAction()
{ }
void DicomEventAction::BeginOfEventAction(const G4Event*)
{ }
void DicomEventAction::BeginOfEventAction(const G4Event* evt)
{
G4cout << "EV: " << evt->GetEventID() << G4endl;
}
void DicomEventAction::EndOfEventAction(const G4Event* evt)
{
@@ -1,388 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// The code was written by :
// *Louis Archambault louis.archambault@phy.ulaval.ca,
// *Luc Beaulieu beaulieu@phy.ulaval.ca
// +Vincent Hubert-Tremblay at tigre.2@sympatico.ca
//
//
// *Centre Hospitalier Universitaire de Quebec (CHUQ),
// Hotel-Dieu de Quebec, departement de Radio-oncologie
// 11 cote du palais. Quebec, QC, Canada, G1R 2J6
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Université Laval, Québec (QC) Canada
//*******************************************************
#include "globals.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4VPhysicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4PVParameterised.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4VisAttributes.hh"
#include "G4Colour.hh"
#include "G4ios.hh"
#include "DicomGeometry.hh"
#include "DicomPatientParameterisation.hh"
#include "DicomPatientConstructor.hh"
#include "DicomConfiguration.hh"
DicomGeometry::DicomGeometry()
{
patientConstructor = new DicomPatientConstructor();
trabecularBone = 0;
denseBone = 0;
liver = 0;
muscle = 0;
phantom = 0;
breast = 0;
adiposeTissue = 0;
lungexhale = 0;
lunginhale = 0;
air = 0;
solidWorld = 0;
logicWorld = 0;
physiWorld = 0;
parameterisedPhysVolume = 0;
physicalLungINhale = 0;
}
DicomGeometry::~DicomGeometry()
{
delete air;
delete lunginhale;
delete lungexhale;
delete adiposeTissue;
delete breast;
delete phantom;
delete muscle;
delete liver;
delete denseBone;
delete trabecularBone;
delete patientConstructor;
}
void DicomGeometry::InitialisationOfMaterials()
{
// Creating elements :
G4double z, a, density;
G4String name, symbol;
G4Element* elC = new G4Element( name = "Carbon",
symbol = "C",
z = 6.0, a = 12.011 * g/mole );
G4Element* elH = new G4Element( name = "Hydrogen",
symbol = "H",
z = 1.0, a = 1.008 * g/mole );
G4Element* elN = new G4Element( name = "Nitrogen",
symbol = "N",
z = 7.0, a = 14.007 * g/mole );
G4Element* elO = new G4Element( name = "Oxygen",
symbol = "O",
z = 8.0, a = 16.00 * g/mole );
G4Element* elNa = new G4Element( name = "Sodium",
symbol = "Na",
z= 11.0, a = 22.98977* g/mole );
G4Element* elS = new G4Element( name = "Sulfur",
symbol = "S",
z = 16.0,a = 32.065* g/mole );
G4Element* elCl = new G4Element( name = "Chlorine",
symbol = "P",
z = 17.0, a = 35.453* g/mole );
G4Element* elK = new G4Element( name = "Potassium",
symbol = "P",
z = 19.0, a = 30.0983* g/mole );
G4Element* elP = new G4Element( name = "Phosphorus",
symbol = "P",
z = 30.0, a = 30.973976* g/mole );
G4Element* elFe = new G4Element( name = "Iron",
symbol = "Fe",
z = 26, a = 56.845* g/mole );
G4Element* elMg = new G4Element( name = "Magnesium",
symbol = "Mg",
z = 12.0, a = 24.3050* g/mole );
G4Element* elCa = new G4Element( name="Calcium",
symbol = "Ca",
z = 20.0, a = 40.078* g/mole );
// Creating Materials :
G4int numberofElements;
// Trabecular Bone
trabecularBone = new G4Material( "SkeletonSpongiosa",
density = 1159*kg/m3,
numberofElements = 12 );
trabecularBone->AddElement(elH,0.085);
trabecularBone->AddElement(elC,0.404);
trabecularBone->AddElement(elN,0.058);
trabecularBone->AddElement(elO,0.367);
trabecularBone->AddElement(elNa,0.001);
trabecularBone->AddElement(elMg,0.001);
trabecularBone->AddElement(elP,0.034);
trabecularBone->AddElement(elS,0.002);
trabecularBone->AddElement(elCl,0.002);
trabecularBone->AddElement(elK,0.001);
trabecularBone->AddElement(elCa,0.044);
trabecularBone->AddElement(elFe,0.001);
// dense Bone
denseBone = new G4Material( "SkeletonRibs",
density = 1575*kg/m3,
numberofElements = 11 );
denseBone->AddElement(elH,0.056);
denseBone->AddElement(elC,0.235);
denseBone->AddElement(elN,0.050);
denseBone->AddElement(elO,0.434);
denseBone->AddElement(elNa,0.001);
denseBone->AddElement(elMg,0.001);
denseBone->AddElement(elP,0.072);
denseBone->AddElement(elS,0.003);
denseBone->AddElement(elCl,0.001);
denseBone->AddElement(elK,0.001);
denseBone->AddElement(elCa,0.146);
// Liver
liver = new G4Material( "Liver",
density = 1071*kg/m3,
numberofElements = 9);
liver->AddElement(elH,0.102);
liver->AddElement(elC,0.139);
liver->AddElement(elN,0.030);
liver->AddElement(elO,0.716);
liver->AddElement(elNa,0.002);
liver->AddElement(elP,0.003);
liver->AddElement(elS,0.003);
liver->AddElement(elCl,0.002);
liver->AddElement(elK,0.003);
// Muscle
muscle = new G4Material( "Muscle",
density = 1061*kg/m3,
numberofElements = 9 );
muscle->AddElement(elH,0.102);
muscle->AddElement(elC,0.143);
muscle->AddElement(elN,0.034);
muscle->AddElement(elO,0.710);
muscle->AddElement(elNa,0.001);
muscle->AddElement(elP,0.002);
muscle->AddElement(elS,0.003);
muscle->AddElement(elCl,0.001);
muscle->AddElement(elK,0.004);
// Phantom
phantom = new G4Material( "Phantom",
density = 1.018*kg/m3,
numberofElements = 2 );
phantom->AddElement(elH,0.112);
phantom->AddElement(elO,0.888);
// Breast
breast = new G4Material( "Breast",
density = 990*kg/m3,
numberofElements = 8 );
breast->AddElement(elH,0.109);
breast->AddElement(elC,0.506);
breast->AddElement(elN,0.023);
breast->AddElement(elO,0.358);
breast->AddElement(elNa,0.001);
breast->AddElement(elP,0.001);
breast->AddElement(elS,0.001);
breast->AddElement(elCl,0.001);
// Adipose tissue
adiposeTissue = new G4Material( "adiposeTissue",
density = 967*kg/m3,
numberofElements = 7);
adiposeTissue->AddElement(elH,0.114);
adiposeTissue->AddElement(elC,0.598);
adiposeTissue->AddElement(elN,0.007);
adiposeTissue->AddElement(elO,0.278);
adiposeTissue->AddElement(elNa,0.001);
adiposeTissue->AddElement(elS,0.001);
adiposeTissue->AddElement(elCl,0.001);
lungexhale = new G4Material( "lungExhale",
density = 508*kg/m3,
numberofElements = 9 );
lungexhale->AddElement(elH,0.103);
lungexhale->AddElement(elC,0.105);
lungexhale->AddElement(elN,0.031);
lungexhale->AddElement(elO,0.749);
lungexhale->AddElement(elNa,0.002);
lungexhale->AddElement(elP,0.002);
lungexhale->AddElement(elS,0.003);
lungexhale->AddElement(elCl,0.002);
lungexhale->AddElement(elK,0.003);
// LungINhale
lunginhale = new G4Material( "lungInhale",
density = 217*kg/m3,
numberofElements = 9);
lunginhale->AddElement(elH,0.103);
lunginhale->AddElement(elC,0.105);
lunginhale->AddElement(elN,0.031);
lunginhale->AddElement(elO,0.749);
lunginhale->AddElement(elNa,0.002);
lunginhale->AddElement(elP,0.002);
lunginhale->AddElement(elS,0.003);
lunginhale->AddElement(elCl,0.002);
lunginhale->AddElement(elK,0.003);
// Air
air = new G4Material( "Air",
1.290*mg/cm3,
numberofElements = 2 );
air->AddElement(elN, 0.7);
air->AddElement(elO, 0.3);
}
void DicomGeometry::PatientConstruction()
{
DicomConfiguration readConfiguration;
readConfiguration.ReadDataFile();
// images must have the same dimension ...
// open a .g4 file to read some values ...
G4int compressionUsed = readConfiguration.IsCompressionUsed();
G4double sliceThickness = readConfiguration.GetSliceThickness();
G4double xPixelSpacing = readConfiguration.GetXPixelSpacing();
G4double yPixelSpacing = readConfiguration.GetYPixelSpacing();
G4int totalNumberOfFile = readConfiguration.GetTotalNumberOfFile();
G4int totalRows = readConfiguration.GetTotalRows();
G4int totalColumns = readConfiguration.GetTotalColumns();
G4double patientX = (compressionUsed*(xPixelSpacing)/2.0) *mm;
G4double patientY = (compressionUsed*(yPixelSpacing)/2.0) *mm;
G4double patientZ = ((sliceThickness/2.0) *mm);
G4VisAttributes* visualisationAttribute = new G4VisAttributes();
visualisationAttribute->SetForceSolid(false);
visualisationAttribute->SetColour( 1.,
0.,
0.,
1. );
G4double middleLocationValue;
G4double maxsl = -999. , minsl = 999.;
for ( G4int i=0; i< totalNumberOfFile;i++ )
{
G4double sliceLoc = readConfiguration.GetSliceLocation()[i];
if(sliceLoc > maxsl) maxsl = sliceLoc;
if(sliceLoc < minsl) minsl = sliceLoc;
}
middleLocationValue = (maxsl + minsl)/2.;
//Building up the parameterisation ...
G4Box* parameterisedBox = new G4Box( "Parameterisation_Mother",
totalColumns*(xPixelSpacing)/2.*mm,
totalRows*(yPixelSpacing)/2.*mm,
(maxsl-minsl+sliceThickness)/2.*mm);
G4LogicalVolume* parameterisedLogicalvolume =
new G4LogicalVolume( parameterisedBox,
air,
"Parameterisation_Mother (logical)" );
parameterisedLogicalvolume->SetVisAttributes(visualisationAttribute);
G4ThreeVector origin( 0.*mm,0.*mm,middleLocationValue*mm );
parameterisedPhysVolume = new G4PVPlacement( 0,
origin,
parameterisedLogicalvolume,
"Parameterisation_Mother_placement",
logicWorld,
false,
0 );
G4Box* LungINhale = new G4Box( "LungINhale", patientX, patientY, patientZ);
G4LogicalVolume* logicLungInHale = new G4LogicalVolume(LungINhale,lunginhale,"Logical_LungINhale",0,0,0);
// ---- MGP ---- Numbers (2.0, 0.207) to be removed from code; move to const
G4int numberOfVoxels = patientConstructor->FindingNbOfVoxels(2.0,0.207);
G4VPVParameterisation* paramLungINhale = new DicomPatientParameterisation
( numberOfVoxels,
2.0 , 0.207 ,
lunginhale,
lungexhale,
adiposeTissue,
breast,
phantom,
muscle,
liver,
denseBone,
trabecularBone );
physicalLungINhale =
new G4PVParameterised( "Physical_LungINhale" ,
logicLungInHale,
parameterisedLogicalvolume,
kZAxis, numberOfVoxels,
paramLungINhale );
// delete ReadConfiguration;
}
G4VPhysicalVolume* DicomGeometry::Construct()
{
InitialisationOfMaterials();
G4double worldXDimension = 1.*m;
G4double worldYDimension = 1.*m;
G4double worldZDimension = 1.*m;
solidWorld = new G4Box( "WorldSolid",
worldXDimension,
worldYDimension,
worldZDimension );
logicWorld = new G4LogicalVolume( solidWorld,
air,
"WorldLogical",
0, 0, 0 );
physiWorld = new G4PVPlacement( 0,
G4ThreeVector(0,0,0),
"World",
logicWorld,
0,
false,
0 );
PatientConstruction();
return physiWorld;
}
@@ -35,7 +35,7 @@
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Universit-Aé Laval, Québec (QC) Canada$)B
// + Universit.A Laval, Qubec (QC) Canada
//*******************************************************
//
//*******************************************************
@@ -45,7 +45,7 @@
// DicomHandler.cc :
// - Handling of DICM images
// - Reading headers and pixels
// - Transforming pixel to density and creating *.g4
// - Transforming pixel to density and creating *.g4dcm
// files
// - Definitions are in DicomHandler.hh
//*******************************************************
@@ -61,7 +61,7 @@
DicomHandler::DicomHandler()
: DATABUFFSIZE(8192), LINEBUFFSIZE(128), FILENAMESIZE(512),
compression(0), max(0), rows(0), columns(0),
compression(0), nFiles(0), rows(0), columns(0),
bitAllocated(0), maxPixelValue(0), minPixelValue(0),
pixelSpacingX(0.), pixelSpacingY(0.),
sliceThickness(0.), sliceLocation(0.),
@@ -75,8 +75,9 @@ DicomHandler::~DicomHandler() {
;
}
G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
G4int DicomHandler::ReadFile(FILE *dicom, char * filename2)
{
G4cout << " ReadFile " << filename2 << G4endl;
G4int returnvalue = 0;
char * buffer = new char[LINEBUFFSIZE];
@@ -108,10 +109,10 @@ G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
readElementId = 0;
// group ID
std::fread(buffer, 2, 1, dicom);
getValue(buffer, readGroupId);
GetValue(buffer, readGroupId);
// element ID
std::fread(buffer, 2, 1, dicom);
getValue(buffer, readElementId);
GetValue(buffer, readElementId);
// Creating a tag to be identified afterward
G4int tagDictionary = readGroupId*0x10000 + readElementId;
@@ -119,7 +120,7 @@ G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
// VR or element length
std::fread(buffer,2,1,dicom);
getValue(buffer, elementLength2);
GetValue(buffer, elementLength2);
// If value representation (VR) is OB, OW, SQ, UN,
//the next length is 32 bits
@@ -133,7 +134,7 @@ G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
// element length
std::fread(buffer, 4, 1, dicom);
getValue(buffer, elementLength4);
GetValue(buffer, elementLength4);
// beginning of the pixels
if(tagDictionary == 0x7FE00010) break;
@@ -147,7 +148,7 @@ G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
if(!implicitEndian || readGroupId == 2) {
// element length (2 bytes)
std::fread(buffer, 2, 1, dicom);
getValue(buffer, elementLength2);
GetValue(buffer, elementLength2);
elementLength4 = elementLength2;
} else {
@@ -157,7 +158,7 @@ G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
exit(-10);
}
std::fread(buffer, 4, 1, dicom);
getValue(buffer, elementLength4);
GetValue(buffer, elementLength4);
}
// beginning of the pixels
@@ -169,12 +170,35 @@ G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
// NULL termination
data[elementLength4] = '\0';
// analyzing inforamtion
getInformation(tagDictionary, data);
// analyzing information
GetInformation(tagDictionary, data);
}
// Creating files to store information
storeInformation(filename2);
std::ofstream foutG4DCM;
G4String fnameG4DCM = G4String(filename2) + ".g4dcm";
foutG4DCM.open(fnameG4DCM);
G4cout << " opened fnameG4DCM file " << fnameG4DCM << G4endl;
foutG4DCM << fMaterialIndices.size() << G4endl;
//--- Write materials
size_t ii = 0;
std::map<G4double,G4String>::const_iterator ite;
for( ite = fMaterialIndices.begin(); ite != fMaterialIndices.end(); ite++, ii++ ){
foutG4DCM << ii << " " << (*ite).second << G4endl;
}
//--- Write number of voxels (assume only one voxel in Z)
foutG4DCM << rows/compression << " " << columns/compression << " 1 " << G4endl;
//--- Write minimum and maximum extensions
foutG4DCM << -pixelSpacingX*rows/2 << " " << pixelSpacingX*rows/2 << G4endl;
foutG4DCM << -pixelSpacingY*columns/2 << " " << pixelSpacingY*columns/2 << G4endl;
foutG4DCM << sliceLocation-sliceThickness/2. << " " << sliceLocation+sliceThickness/2. << G4endl;
ReadData( dicom, filename2 );
StoreData( foutG4DCM );
foutG4DCM.close();
//
delete [] buffer;
@@ -184,35 +208,35 @@ G4int DicomHandler::readHeader(FILE *dicom, char * filename2)
}
//
void DicomHandler::getInformation(G4int & tagDictionary, char * data) {
void DicomHandler::GetInformation(G4int & tagDictionary, char * data) {
if(tagDictionary == 0x00280010 ) { // Number of Rows
getValue(data, rows);
GetValue(data, rows);
std::printf("[0x00280010] Rows -> %i\n",rows);
} else if(tagDictionary == 0x00280011 ) { // Number of columns
getValue(data, columns);
GetValue(data, columns);
std::printf("[0x00280011] Columns -> %i\n",columns);
} else if(tagDictionary == 0x00280102 ) { // High bits ( not used )
short highBits;
getValue(data, highBits);
GetValue(data, highBits);
std::printf("[0x00280102] High bits -> %i\n",highBits);
} else if(tagDictionary == 0x00280100 ) { // Bits allocated
getValue(data, bitAllocated);
GetValue(data, bitAllocated);
std::printf("[0x00280100] Bits allocated -> %i\n", bitAllocated);
} else if(tagDictionary == 0x00280101 ) { // Bits stored ( not used )
short bitStored;
getValue(data, bitStored);
GetValue(data, bitStored);
std::printf("[0x00280101] Bits stored -> %i\n",bitStored);
} else if(tagDictionary == 0x00280106 ) { // Min. pixel value
getValue(data, minPixelValue);
GetValue(data, minPixelValue);
std::printf("[0x00280106] Min. pixel value -> %i\n", minPixelValue);
} else if(tagDictionary == 0x00280107 ) { // Max. pixel value
getValue(data, maxPixelValue);
GetValue(data, maxPixelValue);
std::printf("[0x00280107] Max. pixel value -> %i\n", maxPixelValue);
} else if(tagDictionary == 0x00281053) { // Rescale slope
@@ -324,68 +348,131 @@ void DicomHandler::getInformation(G4int & tagDictionary, char * data) {
}
//
void DicomHandler::storeInformation(char * _filename) {
void DicomHandler::StoreData(std::ofstream& foutG4DCM)
{
G4int mean;
G4double density;
G4bool overflow = false;
G4int cpt=1;
char * compressionbuf = new char[LINEBUFFSIZE];
char * maxbuf = new char[LINEBUFFSIZE];
char * filename = new char[FILENAMESIZE];
compression = 0;
max = 0;
FILE* configuration;
configuration = std::fopen("Data.dat","r");
if( configuration != 0 ) {
std::fscanf(configuration,"%s",compressionbuf);
compression = atoi(compressionbuf);
std::fscanf(configuration,"%s",maxbuf);
max = atoi(maxbuf);
std::fclose(configuration);
} else {
std::printf("### WARNING, file Data.dat not here !!!\n");
exit(1);
//----- Print indices of material
if(compression == 1) { // no compression: each pixel has a density value)
for( G4int ww = 0; ww < rows; ww++) {
for( G4int xx = 0; xx < columns; xx++) {
mean = tab[ww][xx];
density = Pixel2density(mean);
foutG4DCM << GetMaterialIndex( density ) << " ";
}
foutG4DCM << G4endl;
}
} else {
// density value is the average of a square region of
// compression*compression pixels
for(G4int ww = 0; ww < rows ;ww += compression ) {
for(G4int xx = 0; xx < columns ;xx +=compression ) {
overflow = false;
mean = 0;
for(int sumx = 0; sumx < compression; sumx++) {
for(int sumy = 0; sumy < compression; sumy++) {
if(ww+sumy >= rows || xx+sumx >= columns) overflow = true;
mean += tab[ww+sumy][xx+sumx];
}
if(overflow) break;
}
mean /= compression*compression;
cpt = 1;
if(!overflow) {
G4double density = Pixel2density(mean);
foutG4DCM << GetMaterialIndex( density ) << " ";
}
}
foutG4DCM << G4endl;
}
}
FILE* dat;
std::sprintf(filename,"%s.dat", _filename);
dat = std::fopen(filename,"w+");
// Note: the .dat files contain basic information on the images.
//----- Print densities
if(compression == 1) { // no compression: each pixel has a density value)
for( G4int ww = 0; ww < rows; ww++) {
for( G4int xx = 0; xx < columns; xx++) {
mean = tab[ww][xx];
density = Pixel2density(mean);
foutG4DCM << density << " ";
if( xx%8 == 3 ) foutG4DCM << G4endl; // just for nicer reading
}
}
} else {
// density value is the average of a square region of
// compression*compression pixels
for(G4int ww = 0; ww < rows ;ww += compression ) {
for(G4int xx = 0; xx < columns ;xx +=compression ) {
overflow = false;
mean = 0;
for(int sumx = 0; sumx < compression; sumx++) {
for(int sumy = 0; sumy < compression; sumy++) {
if(ww+sumy >= rows || xx+sumx >= columns) overflow = true;
mean += tab[ww+sumy][xx+sumx];
}
if(overflow) break;
}
mean /= compression*compression;
cpt = 1;
if(!overflow) {
G4double density = Pixel2density(mean);
foutG4DCM << density << " ";
if( xx/compression%8 == 3 ) foutG4DCM << G4endl; // just for nicer reading
}
}
}
std::fprintf(dat,"Rows,columns(#): %8i %8i\n",rows,columns);
std::fprintf(dat,"PixelSpacing_X,Y(mm): %8f %8f\n",
pixelSpacingX,pixelSpacingY);
std::fprintf(dat,"SliceThickness(mm): %8f\n",sliceThickness);
std::fprintf(dat,"SliceLocation(mm): %8f\n",sliceLocation);
std::fclose(dat);
}
delete [] compressionbuf;
delete [] maxbuf;
delete [] filename;
}
void DicomHandler::ReadMaterialIndices( std::ifstream& finData)
{
size_t nMate;
G4String mateName;
G4double densityMax;
finData >> nMate;
G4cout << " ReadMaterialIndices " << nMate << G4endl;
for( size_t ii = 0; ii < nMate; ii++ ){
finData >> mateName >> densityMax;
fMaterialIndices[densityMax] = mateName;
G4cout << ii << " ReadMaterialIndices " << mateName << " " << densityMax << G4endl;
}
}
size_t DicomHandler::GetMaterialIndex( G4double density )
{
size_t mateID;
std::map<G4double,G4String>::reverse_iterator ite;
G4int ii = fMaterialIndices.size();
for( ite = fMaterialIndices.rbegin(); ite != fMaterialIndices.rend(); ite++, ii-- ) {
if( density >= (*ite).first ) {
break;
}
}
//- G4cout << " GetMaterialIndex " << density << " = " << ii << G4endl;
return ii;
}
//
G4int DicomHandler::readData(FILE *dicom,char * filename2)
G4int DicomHandler::ReadData(FILE *dicom,char * filename2)
{
G4int returnvalue = 0;
char * compressionbuf = new char[LINEBUFFSIZE];
char * maxbuf = new char[LINEBUFFSIZE];
short compression = 0;
G4int max = 0;
FILE* configuration = std::fopen("Data.dat","r");
std::fscanf(configuration,"%s",compressionbuf);
compression = atoi(compressionbuf);
std::fscanf(configuration,"%s",maxbuf);
max = atoi(maxbuf);
std::fclose(configuration);
// READING THE PIXELS :
G4int w = 0;
G4int len = 0;
G4int** tab = new G4int*[rows];
tab = new G4int*[rows];
for ( G4int i = 0; i < rows; i ++ ) {
tab[i] = new G4int[columns];
}
@@ -416,7 +503,7 @@ G4int DicomHandler::readData(FILE *dicom,char * filename2)
for( G4int i = 0; i < columns; i++) {
w++;
std::fread(sbuff, 2, 1, dicom);
getValue(sbuff, pixel);
GetValue(sbuff, pixel);
tab[j][i] = pixel*rescaleSlope + rescaleIntercept;
}
}
@@ -455,7 +542,7 @@ G4int DicomHandler::readData(FILE *dicom,char * filename2)
for( G4int ww = 0; ww < rows; ww++) {
for( G4int xx = 0; xx < columns; xx++) {
mean = tab[ww][xx];
density = pixel2density(mean);
density = Pixel2density(mean);
std::fwrite(&density, sizeof(G4double), 1, processed);
}
}
@@ -478,7 +565,7 @@ G4int DicomHandler::readData(FILE *dicom,char * filename2)
cpt = 1;
if(!overflow) {
G4double density = pixel2density(mean);
G4double density = Pixel2density(mean);
std::fwrite(&density, sizeof(G4double), 1, processed);
}
}
@@ -487,14 +574,13 @@ G4int DicomHandler::readData(FILE *dicom,char * filename2)
}
std::fclose(processed);
delete [] compressionbuf;
delete [] maxbuf;
delete [] nameProcessed;
for ( G4int i = 0; i < rows; i ++ ) {
/* for ( G4int i = 0; i < rows; i ++ ) {
delete [] tab[i];
}
delete [] tab;
*/
return returnvalue;
}
@@ -511,7 +597,7 @@ G4int DicomHandler::readData(FILE *dicom,char * filename2)
}
*/
G4double DicomHandler::pixel2density(G4int pixel)
G4double DicomHandler::Pixel2density(G4int pixel)
{
G4double density = -1.;
G4int nbrequali = 0;
@@ -560,11 +646,10 @@ G4double DicomHandler::pixel2density(G4int pixel)
}
void DicomHandler::checkFileFormat()
void DicomHandler::CheckFileFormat()
{
std::ifstream checkData("Data.dat");
char * oneLine = new char[128];
G4int nbImages;
if(!(checkData.is_open())) { //Check existance of Data.dat
@@ -575,30 +660,33 @@ void DicomHandler::checkFileFormat()
exit(0);
}
checkData >> nbImages;
checkData >> nbImages;
checkData >> compression;
checkData >> nFiles;
G4String oneName;
checkData.getline(oneLine,100);
std::ifstream testExistence;
G4bool existAlready = true;
for(G4int rep = 0; rep < nbImages; rep++) {
checkData.getline(oneLine,100);
oneName = oneLine;
oneName += ".g4"; // create dicomFile.g4
testExistence.open(oneName.data());
if(!(testExistence.is_open())) {
existAlready = false;
testExistence.clear();
testExistence.close();
break;
}
for(G4int rep = 0; rep < nFiles; rep++) {
checkData.getline(oneLine,100);
oneName = oneLine;
oneName += ".g4dcm"; // create dicomFile.g4dcm
G4cout << nFiles << " test file " << oneName << G4endl;
testExistence.open(oneName.data());
if(!(testExistence.is_open())) {
existAlready = false;
testExistence.clear();
testExistence.close();
}
testExistence.clear();
testExistence.close();
}
ReadMaterialIndices( checkData );
checkData.close();
delete [] oneLine;
if( existAlready == false ) { // The files *.g4 have to be created
if( existAlready == false ) { // The files *.g4dcm have to be created
G4cout << "\nAll the necessary images were not found in processed form, starting "
<< "with .dcm images\n";
@@ -615,9 +703,10 @@ void DicomHandler::checkFileFormat()
std::fscanf(lecturePref,"%s",compressionc);
compression = atoi(compressionc);
std::fscanf(lecturePref,"%s",maxc);
max = atoi(maxc);
nFiles = atoi(maxc);
G4cout << " nFiles " << nFiles << G4endl;
for( G4int i = 1; i <= max; i++ ) { // Begin loop on filenames
for( G4int i = 1; i <= nFiles; i++ ) { // Begin loop on filenames
std::fscanf(lecturePref,"%s",inputFile);
std::sprintf(name,"%s.dcm",inputFile);
@@ -629,11 +718,9 @@ void DicomHandler::checkFileFormat()
// 1. reading the header
// 2. reading the pixel data and store the density in Moyenne.dat
if( dicom != 0 ) {
readHeader(dicom,inputFile);
readData(dicom,inputFile);
ReadFile(dicom,inputFile);
} else {
G4cout << "\nError opening file : " << name << G4endl;
exit(0);
}
std::fclose(dicom);
}
@@ -650,7 +737,7 @@ void DicomHandler::checkFileFormat()
template <class Type>
void DicomHandler::getValue(char * _val, Type & _rval) {
void DicomHandler::GetValue(char * _val, Type & _rval) {
#if BYTE_ORDER == BIG_ENDIAN
if(littleEndian) { // little endian
@@ -0,0 +1,122 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
///////////////////////////////////////////////////////////////////////////////
#include "DicomNestedPhantomParameterisation.hh"
#include "G4VPhysicalVolume.hh"
#include "G4VTouchable.hh"
#include "G4ThreeVector.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4Material.hh"
DicomNestedPhantomParameterisation::DicomNestedPhantomParameterisation(
const G4ThreeVector& voxelSize,
std::vector<G4Material*>& mat):
G4VNestedParameterisation(),fdX(voxelSize.x()),fdY(voxelSize.y()),fdZ(voxelSize.z()),fMaterials(mat)
{
// Position of voxels.
// x and y positions are already defined in DetectorConstruction
// by using replicated volume. Here only we need to define is z positions of voxes.
}
DicomNestedPhantomParameterisation::~DicomNestedPhantomParameterisation()
{
}
void DicomNestedPhantomParameterisation::SetNoVoxel( size_t nx, size_t ny, size_t nz )
{
fnX = nx;
fnY = ny;
fnZ = nz;
}
//
// Material assignment to geometry.
//
G4Material* DicomNestedPhantomParameterisation::ComputeMaterial(G4VPhysicalVolume* ,
const G4int copyNoZ,
const G4VTouchable* parentTouch)
{
if(parentTouch==0) return fMaterials[0]; // protection for initialization and vis at idle state
// Copy number of voxels.
// Copy number of X and Y are obtained from replication number.
// Copy nymber of Z is the copy number of current voxel.
G4int ix = parentTouch->GetReplicaNumber(0);
G4int iy = parentTouch->GetReplicaNumber(1);
G4int iz = copyNoZ;
G4int copyNo = ix + fnZ*iy + fnX*fnY*iz;
size_t matIndex = GetMaterialIndex(copyNo);
return fMaterials[ matIndex ];
}
//------------------------------------------------------------------
size_t DicomNestedPhantomParameterisation::
GetMaterialIndex( size_t copyNo ) const
{
return *(fMaterialIndices+copyNo);
}
//
// Number of Materials
// Material scanner is required for preparing physics tables and so on before
// stating simulation, so that G4 has to know number of materials.
G4int DicomNestedPhantomParameterisation::GetNumberOfMaterials() const{
return fMaterials.size();
}
//
// GetMaterial
// This is needed for material scanner and realizing geometry.
//
G4Material* DicomNestedPhantomParameterisation::GetMaterial(G4int i) const{
return fMaterials[i];
}
//
// Transformation of voxels.
//
void DicomNestedPhantomParameterisation::ComputeTransformation(const G4int copyNo,
G4VPhysicalVolume* physVol)const{
G4ThreeVector position(0.,0.,(2*copyNo+1)*fdZ - fdZ*fnZ);
physVol->SetTranslation(position);
}
//
// Dimensions are always same in this RE02 example.
//
void DicomNestedPhantomParameterisation::ComputeDimensions(G4Box& box,
const G4int ,
const G4VPhysicalVolume* ) const{
box.SetXHalfLength(fdX);
box.SetYHalfLength(fdY);
box.SetZHalfLength(fdZ);
}
@@ -1,157 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// The code was written by :
// *Louis Archambault louis.archambault@phy.ulaval.ca,
// *Luc Beaulieu beaulieu@phy.ulaval.ca
// +Vincent Hubert-Tremblay at tigre.2@sympatico.ca
//
//
// *Centre Hospitalier Universitaire de Quebec (CHUQ),
// Hotel-Dieu de Quebec, departement de Radio-oncologie
// 11 cote du palais. Quebec, QC, Canada, G1R 2J6
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Université Laval, Québec (QC) Canada
//*******************************************************
#include "DicomOctree.hh"
#include "DicomOctreeNode.hh"
#include "DicomOctreeMiddleNode.hh"
#include "DicomOctreeTerminalNode.hh"
#include "G4ios.hh"
DicomOctree::DicomOctree( G4int noLevels, G4double size )
{
std::cout << "++++++ DicomOctree was instantiated now." << std::endl;
mNoLevels = noLevels;
mSize = size;
mRoot = new DicomOctreeMiddleNode(0);
}
DicomOctree::~DicomOctree()
{
delete mRoot;
mRoot = 0;
}
DicomOctreeNode* DicomOctree::CreateNode( G4double nodeX, G4double nodeY, G4double nodeZ, G4int level )
{
DicomOctreeNode* current = mRoot;
G4double currentX = 0;
G4double currentY = 0;
G4double currentZ = 0;
indexChild = 8;
for ( G4int i = 0; i < indexChild; i++ ) // Make children
{
G4double childLevelResolution = (1 << (i+1) );
G4double childSize = mSize / childLevelResolution;
G4int dirX = G4int( nodeX >= currentX + childSize );
G4int dirY = G4int( nodeY >= currentY + childSize );
G4int dirZ = G4int( nodeZ >= currentZ + childSize );
G4int direction = dirX + ( dirY << 1 ) + ( dirZ << 2 );
if ( (*current)[direction] == 0 )
{
if ( i < level - 1 )
{
(*current)[direction] = new DicomOctreeMiddleNode( current );
} else
{
(*current)[direction] = new DicomOctreeTerminalNode( current );
}
}
current = (*current)[direction];
currentX += dirX*childSize;
currentY += dirY*childSize;
currentZ += dirZ*childSize;
}
return current;
}
DicomOctreeNode* DicomOctree::operator()( G4double nodeX,
G4double nodeY,
G4double nodeZ,
G4int level )
{
DicomOctreeNode* current = mRoot;
G4double currentX = 0;
G4double currentY = 0;
G4double currentZ = 0;
// Make children
for ( G4int i = 0; i < level; i++ )
{
G4double childLevelResolution = ( 1 << (i+1) );
G4double childSize = mSize / childLevelResolution;
G4int dirX = G4int( nodeX >= currentX + childSize );
G4int dirY = G4int( nodeY >= currentY + childSize );
G4int dirZ = G4int( nodeZ >= currentZ + childSize );
G4int direction = dirX + ( dirY << 1 ) + ( dirZ << 2 );
if ( (*current)[direction] == 0 ) return 0;
current = (*current)[direction];
currentX += dirX*childSize;
currentY += dirY*childSize;
currentZ += dirZ*childSize;
}
return current;
}
void DicomOctree::DeleteTree()
{
delete mRoot;
mRoot = 0;
}
void DicomOctree::CountRecursive( DicomOctreeNode* pNode,
G4int rMiddle,
G4int rTerminal )
{
if ( pNode->Type() == MIDDLE_NODE )rMiddle++;
else rTerminal++;
for ( G4int i = 0; i < 8; i++ )
{
if ( (*pNode)[i] != 0 )
CountRecursive( (*pNode)[i], rMiddle, rTerminal );
}
}
G4int DicomOctree::CountMemory( G4int rMiddle, G4int rTerminal )
{
CountRecursive( mRoot, rMiddle, rTerminal );
G4int total = rMiddle*sizeof(DicomOctreeMiddleNode) +
rTerminal*sizeof(DicomOctreeTerminalNode);
return total;
}
@@ -1,83 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// The code was written by :
// *Louis Archambault louis.archambault@phy.ulaval.ca,
// *Luc Beaulieu beaulieu@phy.ulaval.ca
// +Vincent Hubert-Tremblay at tigre.2@sympatico.ca
//
//
// *Centre Hospitalier Universitaire de Quebec (CHUQ),
// Hotel-Dieu de Quebec, departement de Radio-oncologie
// 11 cote du palais. Quebec, QC, Canada, G1R 2J6
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Université Laval, Québec (QC) Canada
//*******************************************************
#include "DicomOctreeNode.hh"
#include "DicomOctreeMiddleNode.hh"
#include "DicomOctree.hh"
DicomOctreeMiddleNode::DicomOctreeMiddleNode()
{
ResetFamily();
}
DicomOctreeMiddleNode::~DicomOctreeMiddleNode()
{
for ( G4int i = 0; i < 8; i++ )
{
if ( mChildren[i] != 0 ) delete mChildren[i];
}
}
void DicomOctreeMiddleNode::ResetFamily()
{
// ---- MGP ---- Remove explicit numbers in code
for ( G4int i = 0; i < 8; i++ ) mChildren[i] = 0;
}
DicomOctreeMiddleNode::DicomOctreeMiddleNode( DicomOctreeNode* pParent ) : DicomOctreeNode( pParent )
{
ResetFamily();
}
G4int DicomOctreeMiddleNode::FindChild( const DicomOctreeNode* pNode )
{
for ( G4int i = 0; i < 8; i++ )
{
if ( mChildren[i] == pNode ) return i;
}
return -1;
}
G4int DicomOctreeMiddleNode::MemSize()
{
return sizeof(DicomOctreeMiddleNode);
}
@@ -1,72 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// The code was written by :
// *Louis Archambault louis.archambault@phy.ulaval.ca,
// *Luc Beaulieu beaulieu@phy.ulaval.ca
// +Vincent Hubert-Tremblay at tigre.2@sympatico.ca
//
//
// *Centre Hospitalier Universitaire de Quebec (CHUQ),
// Hotel-Dieu de Quebec, departement de Radio-oncologie
// 11 cote du palais. Quebec, QC, Canada, G1R 2J6
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Université Laval, Québec (QC) Canada
//*******************************************************
//*******************************************************
//
// DicomPatientConstructor.cc :
// - Initialisation of the construction of DICM images
// - Reading contour information included in Plan.roi
// (Region of interest) *** NOT FULLY WORKING YET ***
// - Definitions are in DicomGeometry.hh
//
//*******************************************************
#include "DicomConfiguration.hh"
#include "DicomPatientConstructor.hh"
#include "globals.hh"
G4int DicomPatientConstructor::FindingNbOfVoxels(G4double maxDensity , G4double minDensity) {
DicomConfiguration dicomConfiguration;
G4double density;
G4int npass = 0;
G4int npixels = dicomConfiguration.GetTotalPixels();
for(int i = 0; i < npixels; i++) {
density = dicomConfiguration.GetDensityValue(i);
if(density >= minDensity && density <= maxDensity) npass++;
}
return npass;
}
@@ -1,367 +0,0 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// The code was written by :
// *Louis Archambault louis.archambault@phy.ulaval.ca,
// *Luc Beaulieu beaulieu@phy.ulaval.ca
// +Vincent Hubert-Tremblay at tigre.2@sympatico.ca
//
//
// *Centre Hospitalier Universitaire de Quebec (CHUQ),
// Hotel-Dieu de Quebec, departement de Radio-oncologie
// 11 cote du palais. Quebec, QC, Canada, G1R 2J6
// tel (418) 525-4444 #6720
// fax (418) 691 5268
//
// + Universit.A Laval, Qubec (QC) Canada
//*******************************************************
#include "DicomPatientParameterisation.hh"
#include "DicomConfiguration.hh"
#include "G4VPhysicalVolume.hh"
#include "G4ThreeVector.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4Material.hh"
#include "G4VisAttributes.hh"
DicomPatientParameterisation::DicomPatientParameterisation(G4int, // NoVoxels,
G4double maxDensity,
G4double minDensity ,
G4Material* lunginhale,
G4Material* lungexhale,
G4Material* adipose,
G4Material* breast,
G4Material* phantom,
G4Material* muscle,
G4Material* liver,
G4Material* denseBone,
G4Material* trabecularBone) {
lungExhale = lungexhale;
lungInhale = lunginhale;
adiposeTissue = adipose;
breastTissue = breast;
phantomTissue = phantom;
muscleTissue = muscle;
liverTissue = liver;
denseBoneTissue = denseBone;
trabecularBoneTissue = trabecularBone;
density.clear();
DicomConfiguration dicomConfiguration;
// images must have the same dimension
G4int totalNumberOfFile = dicomConfiguration.GetTotalNumberOfFile();
G4double maxsl = -999. , minsl = 999.;
for( G4int i = 0; i < totalNumberOfFile; i++) {
G4double sliceLocation = dicomConfiguration.GetSliceLocation()[i];
if(sliceLocation > maxsl) maxsl = sliceLocation;
if(sliceLocation < minsl) minsl = sliceLocation;
}
middleLocationValue = (maxsl + minsl)*0.5;
//
readColorChart();
G4double alpha;
attributeLungINhale = new G4VisAttributes;
attributeLungINhale->SetColour(getChartColor(ColorChart::CRED, 0.217),
getChartColor(ColorChart::CGREEN, 0.217),
getChartColor(ColorChart::CBLUE, 0.217),
alpha=1.);
attributeLungINhale->SetForceSolid(true);
attributeLungEXhale = new G4VisAttributes;
attributeLungEXhale->SetColour(getChartColor(ColorChart::CRED, 0.508),
getChartColor(ColorChart::CGREEN, 0.508),
getChartColor(ColorChart::CBLUE, 0.508),
alpha=1.);
attributeLungEXhale->SetForceSolid(true);
attributeAdipose = new G4VisAttributes;
attributeAdipose->SetColour(getChartColor(ColorChart::CRED, 0.967),
getChartColor(ColorChart::CGREEN, 0.967),
getChartColor(ColorChart::CBLUE, 0.967),
alpha=1.);
attributeAdipose->SetForceSolid(true);
attributeBreast = new G4VisAttributes;
attributeBreast->SetColour(getChartColor(ColorChart::CRED, 0.99),
getChartColor(ColorChart::CGREEN, 0.99),
getChartColor(ColorChart::CBLUE, 0.99),
alpha=1.);
attributeBreast->SetForceSolid(true);
attributePhantom = new G4VisAttributes;
attributePhantom->SetColour(getChartColor(ColorChart::CRED, 1.018),
getChartColor(ColorChart::CGREEN, 1.018),
getChartColor(ColorChart::CBLUE, 1.018),
alpha=1.);
attributePhantom->SetForceSolid(true);
attributeMuscle = new G4VisAttributes;
attributeMuscle->SetColour(getChartColor(ColorChart::CRED, 1.061),
getChartColor(ColorChart::CGREEN, 1.061),
getChartColor(ColorChart::CBLUE, 1.061),
alpha=1.);
attributeMuscle->SetForceSolid(true);
attributeLiver = new G4VisAttributes;
attributeLiver->SetColour(getChartColor(ColorChart::CRED, 1.071),
getChartColor(ColorChart::CGREEN, 1.071),
getChartColor(ColorChart::CBLUE, 1.071),
alpha=1.);
attributeLiver->SetForceSolid(true);
attributeTrabecularBone = new G4VisAttributes;
attributeTrabecularBone->SetColour(getChartColor(ColorChart::CRED, 1.159),
getChartColor(ColorChart::CGREEN, 1.159),
getChartColor(ColorChart::CBLUE, 1.159),
alpha=1.);
attributeTrabecularBone->SetForceSolid(true);
attributeDenseBone = new G4VisAttributes;
attributeDenseBone->SetColour(getChartColor(ColorChart::CRED, 1.575),
getChartColor(ColorChart::CGREEN, 1.575),
getChartColor(ColorChart::CBLUE, 1.575),
alpha=1.);
attributeDenseBone->SetForceSolid(true);
attributeAir = new G4VisAttributes;
attributeAir->SetColour(getChartColor(ColorChart::CRED, 1.),
getChartColor(ColorChart::CGREEN, 1.),
getChartColor(ColorChart::CBLUE, 1.),
alpha=1.);
attributeAir->SetForceSolid(false);
rows = dicomConfiguration.GetTotalRows();
columns = dicomConfiguration.GetTotalColumns();
compression = dicomConfiguration.GetCompressionValue();
max = dicomConfiguration.GetTotalNumberOfFile();
pixelSpacingX = dicomConfiguration.GetXPixelSpacing();
pixelSpacingY = dicomConfiguration.GetYPixelSpacing();
sliceThickness = dicomConfiguration.GetSliceThickness();
GetDensity( maxDensity , minDensity );
dicomConfiguration.ClearDensityData();
}
DicomPatientParameterisation::~DicomPatientParameterisation() {
// visualisation attributes ...
delete attributeAdipose;
delete attributeLungEXhale;
delete attributeBreast;
delete attributePhantom;
delete attributeMuscle;
delete attributeLiver;
delete attributeTrabecularBone;
delete attributeLungINhale;
delete attributeDenseBone;
delete attributeAir;
// materials ...
delete trabecularBoneTissue;
delete denseBoneTissue;
delete liverTissue;
delete muscleTissue;
delete breastTissue;
delete adiposeTissue;
delete lungInhale;
delete lungExhale;
}
void DicomPatientParameterisation::ComputeTransformation(const G4int copyNo, G4VPhysicalVolume* physVol) const
{
G4double originZ = patientPlacementZ[copyNo]*mm-middleLocationValue*mm-sliceThickness/2;
G4ThreeVector origin( patientPlacementX[copyNo]*mm,
patientPlacementY[copyNo]*mm,
originZ*mm );
physVol->SetTranslation(origin);
}
void DicomPatientParameterisation::ComputeDimensions(G4Box& voxels, const G4int, const G4VPhysicalVolume*) const
{
voxels.SetXHalfLength((pixelSpacingX * compression/2.0) * mm);
voxels.SetYHalfLength((pixelSpacingY * compression/2.0) * mm);
voxels.SetZHalfLength((sliceThickness / 2.0) * mm);
}
G4Material*
DicomPatientParameterisation::ComputeMaterial(const G4int copyNo,
G4VPhysicalVolume* physVol,
const G4VTouchable*)
{
if( density[copyNo] >= 0.207 && density[copyNo] <= 0.227 ) {
physVol->SetName("PhysicalLungINhale");
physVol->GetLogicalVolume()->SetVisAttributes( attributeLungINhale );
return lungInhale;
} else if( density[copyNo] >= 0.481 && density[copyNo] <= 0.534 ) {
physVol->SetName("PhysicalLungEXhale");
physVol->GetLogicalVolume()->SetVisAttributes( attributeLungEXhale );
return lungExhale;
} else if( density[copyNo] >= 0.919 && density[copyNo] <= 0.979 ) {
physVol->SetName("PhysicalAdipose");
physVol->GetLogicalVolume()->SetVisAttributes( attributeAdipose );
return adiposeTissue;
} else if( density[copyNo] > 0.979 && density[copyNo] <= 1.004 ) {
physVol->SetName("PhysicalBreast");
physVol->GetLogicalVolume()->SetVisAttributes( attributeBreast );
return breastTissue;
} else if( density[copyNo] > 1.004 && density[copyNo] <= 1.043 ) {
physVol->SetName("PhysicalPhantom");
physVol->GetLogicalVolume()->SetVisAttributes( attributePhantom );
return phantomTissue;
} else if( density[copyNo] > 1.043 && density[copyNo] <= 1.109 ) {
physVol->SetName("PhysicalMuscle");
physVol->GetLogicalVolume()->SetVisAttributes( attributeMuscle );
return muscleTissue;
} else if( density[copyNo] > 1.109 && density[copyNo] <= 1.113 ) {
physVol->SetName("PhysicalLiver");
physVol->GetLogicalVolume()->SetVisAttributes( attributeLiver );
return liverTissue;
} else if( density[copyNo] > 1.113 && density[copyNo] <= 1.217 ) {
physVol->SetName("PhysicalTrabecularBone");
physVol->GetLogicalVolume()->SetVisAttributes( attributeTrabecularBone );
return trabecularBoneTissue;
} else if( density[copyNo] > 1.496 && density[copyNo] <= 1.654 ) {
physVol->SetName("PhysicalDenseBone");
physVol->GetLogicalVolume()->SetVisAttributes( attributeDenseBone );
return denseBoneTissue;
}
return physVol->GetLogicalVolume()->GetMaterial();
}
void DicomPatientParameterisation::GetDensity(G4double maxdensity, G4double mindensity) {
DicomConfiguration dicomConfiguration;
G4int copyCounter = 0;
G4int totalNumberOfFile = dicomConfiguration.GetTotalNumberOfFile();
G4int lenRows = rows/compression;
G4int lenColumns = columns/compression;
G4double xDimension = (lenColumns*pixelSpacingX)/2;
G4int i = 0;
for( G4int z = 0; z < totalNumberOfFile; z++ ) {
G4double slicePosition = dicomConfiguration.GetSliceLocation()[z];
for( G4int j = 1; j <= lenRows; j++ ) {
for( G4int w = 1; w <= lenColumns; w++ ) {
G4double tissueDensity = dicomConfiguration.GetDensityValue(i++);
if( tissueDensity != -1 ) {
if( tissueDensity >= mindensity && tissueDensity <= maxdensity ) {
density.push_back( tissueDensity );
copyCounter++;
G4double yPixel = (pixelSpacingY/2 + (w-1)*pixelSpacingY);
G4double yDimension = ((lenRows*pixelSpacingX)/2)-(pixelSpacingY/2+(j-1)*pixelSpacingY);
patientPlacementX.push_back( ( compression*(xDimension- yPixel ) ) *mm );
patientPlacementY.push_back( ( compression* yDimension ) *mm );
patientPlacementZ.push_back( ( slicePosition + sliceThickness/2 ) *mm );
}
}
}
}
}
}
void DicomPatientParameterisation::readColorChart() {
std::ifstream cm("Colormap.dat");
if(!cm) {
G4cerr << "Colormap.dat couldn't be opened!!" << G4endl;
numColorChart = 2;
ColorChart cc;
cc.density = 0.;
cc.color[ColorChart::CRED] = 0.;
cc.color[ColorChart::CGREEN] = 0.;
cc.color[ColorChart::CBLUE] = 0.;
cc.alpha = 1.;
colorChart.push_back(cc);
cc.density = 4.;
cc.color[ColorChart::CRED] = 1.;
cc.color[ColorChart::CGREEN] = 1.;
cc.color[ColorChart::CBLUE] = 1.;
cc.alpha = 1.;
colorChart.push_back(cc);
return;
}
cm >> numColorChart;
ColorChart cc;
for(int i = 0; i < numColorChart; i++) {
cm >> cc.density
>> cc.color[ColorChart::CRED]
>> cc.color[ColorChart::CGREEN]
>> cc.color[ColorChart::CBLUE]
>> cc.alpha;
colorChart.push_back(cc);
}
}
G4double DicomPatientParameterisation::getChartColor(G4int CC, G4double density) {
G4double color = 0.;
for(int i = 0; i < numColorChart; i++) {
if(density <= colorChart[i].density) {
G4double w = (density - colorChart[i-1].density)
/(colorChart[i].density - colorChart[i-1].density);
color = w*colorChart[i-1].color[CC] + (1-w)*colorChart[i].color[CC];
return color;
}
}
return color;
}
@@ -0,0 +1,176 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
#include "globals.hh"
#include "G4LogicalVolume.hh"
#include "G4MaterialTable.hh"
#include "G4Material.hh"
#include "G4GeometryTolerance.hh"
#include "DicomPatientZSliceHeader.hh"
//-------------------------------------------------------------
DicomPatientZSliceHeader::DicomPatientZSliceHeader( const DicomPatientZSliceHeader& rhs )
{
fNoVoxelX = rhs.GetNoVoxelX();
fNoVoxelY = rhs.GetNoVoxelY();
fNoVoxelZ = rhs.GetNoVoxelZ();
fMinX = rhs.GetMinX();
fMaxX = rhs.GetMaxX();
fMinY = rhs.GetMinY();
fMaxY = rhs.GetMaxY();
fMinZ = rhs.GetMinZ();
fMaxZ = rhs.GetMaxZ();
fMaterialNames = rhs.GetMaterialNames();
}
//-------------------------------------------------------------
DicomPatientZSliceHeader::DicomPatientZSliceHeader( std::ifstream& fin )
{
//----- Read material indices and names
G4int nmate;
G4String mateindex;
G4String matename;
fin >> nmate;
#ifdef G4VERBOSE
G4cout << " DicomPatientZSliceHeader reading number of materials " << nmate << G4endl;
#endif
for( G4int im = 0; im < nmate; im++ ){
fin >> mateindex >> matename;
#ifdef G4VERBOSE
G4cout << " DicomPatientZSliceHeader reading material " << im << " : " << mateindex << " " << matename << G4endl;
#endif
if( ! CheckMaterialExists( matename ) ) {
G4Exception("DicomPatientZSliceHeader::DicomPatientZSliceHeader","A material is found in file that is not built in the C++ code",FatalErrorInArgument,matename.c_str());
}
fMaterialNames.push_back(matename);
}
//----- Read number of voxels
fin >> fNoVoxelX >> fNoVoxelY >> fNoVoxelZ;
#ifdef G4VERBOSE
G4cout << " Number of voxels " << fNoVoxelX << " " << fNoVoxelY << " " << fNoVoxelZ << G4endl;
#endif
//----- Read minimal and maximal extensions (= walls of patient)
fin >> fMinX >> fMaxX;
fin >> fMinY >> fMaxY;
fin >> fMinZ >> fMaxZ;
#ifdef G4VERBOSE
G4cout << " Extension in X " << fMinX << " " << fMaxX << G4endl
<< " Extension in Y " << fMinY << " " << fMaxY << G4endl
<< " Extension in Z " << fMinZ << " " << fMaxZ << G4endl;
#endif
}
//-------------------------------------------------------------
G4bool DicomPatientZSliceHeader::CheckMaterialExists( const G4String& mateName )
{
G4bool bFound = FALSE;
const G4MaterialTable* matTab = G4Material::GetMaterialTable();
std::vector<G4Material*>::const_iterator matite;
for( matite = matTab->begin(); matite != matTab->end(); matite++ ) {
if( (*matite)->GetName() == mateName ) {
bFound = TRUE;
break;
}
}
return bFound;
}
//-------------------------------------------------------------
void DicomPatientZSliceHeader::operator+=( const DicomPatientZSliceHeader& rhs )
{
*this = *this + rhs;
}
//-------------------------------------------------------------
DicomPatientZSliceHeader DicomPatientZSliceHeader::operator+( const DicomPatientZSliceHeader& rhs )
{
//----- Check that both slices has the same dimensions
if( fNoVoxelX != rhs.GetNoVoxelX()
|| fNoVoxelY != rhs.GetNoVoxelY() ) {
G4cerr << "DicomPatientZSliceHeader error adding two slice headers: !!! Different number of voxels: "
<< " X= " << fNoVoxelX << " =? " << rhs.GetNoVoxelX()
<< " Y= " << fNoVoxelY << " =? " << rhs.GetNoVoxelY()
<< " Z= " << fNoVoxelZ << " =? " << rhs.GetNoVoxelZ()
<< G4endl;
G4Exception("");
}
//----- Check that both slices has the same extensions
if( fMinX != rhs.GetMinX() || fMaxX != rhs.GetMaxX()
|| fMinY != rhs.GetMinY() || fMaxY != rhs.GetMaxY() ) {
G4cerr << "DicomPatientZSliceHeader error adding two slice headers: !!! Different extensions: "
<< " Xmin= " << fMinX << " =? " << rhs.GetMinX()
<< " Xmax= " << fMaxX << " =? " << rhs.GetMaxX()
<< " Ymin= " << fMinY << " =? " << rhs.GetMinY()
<< " Ymax= " << fMaxY << " =? " << rhs.GetMaxY()
<< G4endl;
G4Exception("");
}
//----- Check that both slices has the same materials
std::vector<G4String> fMaterialNames2 = rhs.GetMaterialNames();
if( fMaterialNames.size() != fMaterialNames2.size() ) {
G4cerr << "DicomPatientZSliceHeader error adding two slice headers: !!! Different number of materials: " << fMaterialNames.size() << " =? " << fMaterialNames2.size() << G4endl;
G4Exception("");
}
for( size_t ii = 0; ii < fMaterialNames.size(); ii++ ) {
if( fMaterialNames[ii] != fMaterialNames2[ii] ) {
G4cerr << "DicomPatientZSliceHeader error adding two slice headers: !!! Different material number " << ii << " : " << fMaterialNames[ii] << " =? " << fMaterialNames2[ii] << G4endl;
G4Exception("");
}
}
//----- Check that the slices are contiguous in Z
if( std::fabs( fMinZ - rhs.GetMaxZ() ) > G4GeometryTolerance::GetInstance()->GetRadialTolerance() &&
std::fabs( fMaxZ - rhs.GetMinZ() ) > G4GeometryTolerance::GetInstance()->GetRadialTolerance() ){
G4cerr << "DicomPatientZSliceHeader error adding two slice headers: !!! Slices are not contiguous in Z "
<< " Zmin= " << fMinZ << " & " << rhs.GetMinZ()
<< " Zmax= " << fMaxZ << " & " << rhs.GetMaxZ()
<< G4endl;
G4Exception("");
}
//----- Build slice header copying first one
DicomPatientZSliceHeader temp( *this );
//----- Add data from second slice header
temp.SetMinZ( std::min( fMinZ, rhs.GetMinZ() ) );
temp.SetMaxZ( std::max( fMaxZ, rhs.GetMaxZ() ) );
temp.SetNoVoxelZ( fNoVoxelZ + rhs.GetNoVoxelZ() );
return temp;
}
@@ -0,0 +1,94 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// --------------------------------------------------------------------
#include "DicomPhantomParameterisationColour.hh"
#include "globals.hh"
#include "G4VisAttributes.hh"
#include "G4Material.hh"
#include "G4VPhysicalVolume.hh"
#include "G4LogicalVolume.hh"
//------------------------------------------------------------------
DicomPhantomParameterisationColour::DicomPhantomParameterisationColour()
{
ReadColourData();
}
//------------------------------------------------------------------
DicomPhantomParameterisationColour::~DicomPhantomParameterisationColour()
{
}
//------------------------------------------------------------------
void DicomPhantomParameterisationColour::ReadColourData()
{
//----- Add a G4VisAttributes for materials not defined in file;
G4VisAttributes* blankAtt = new G4VisAttributes;
blankAtt->SetVisibility( FALSE );
fColours["Default"] = blankAtt;
//----- Read file
std::ifstream fin("ColourMap.dat");
G4int nMate;
G4String mateName;
G4double cred, cgreen, cblue, copacity;
fin >> nMate;
for( G4int ii = 0; ii < nMate; ii++ ){
fin >> mateName >> cred >> cgreen >> cblue >> copacity;
G4Colour colour( cred, cgreen, cblue, copacity );
G4VisAttributes* visAtt = new G4VisAttributes( colour );
fColours[mateName] = visAtt;
}
}
//------------------------------------------------------------------
G4Material* DicomPhantomParameterisationColour::
ComputeMaterial(const G4int copyNo, G4VPhysicalVolume * physVol, const G4VTouchable *)
{
G4Material* mate = G4PhantomParameterisation::ComputeMaterial( copyNo, physVol, 0 );
if( physVol ) {
G4String mateName = mate->GetName();
size_t iuu = mateName.find("__");
if( iuu != std::string::npos ) {
mateName = mateName.substr( 0, iuu );
}
std::map<G4String,G4VisAttributes*>::const_iterator ite = fColours.find(mateName);
if( ite != fColours.end() ){
const G4Colour col = ((*ite).second)->GetColour();
physVol->GetLogicalVolume()->SetVisAttributes( (*ite).second );
} else {
physVol->GetLogicalVolume()->SetVisAttributes( (*(fColours.begin()) ).second ); // set it as unseen
}
}
return mate;
}
@@ -36,6 +36,8 @@
// fax (418) 691 5268
//
// + Université Laval, Québec (QC) Canada
//
// History: 30.11.07 P.Arce default cut changed to 1 mm
//*******************************************************
#include "DicomPhysicsList.hh"
@@ -51,8 +53,8 @@
DicomPhysicsList::DicomPhysicsList(): G4VUserPhysicsList()
{
defaultCutValue = 10.*mm;
cutForGamma = 10.*mm;
defaultCutValue = 1.e-3*mm;
cutForGamma = 1.e-3*mm;
cutForElectron = defaultCutValue;
cutForPositron = defaultCutValue;
@@ -43,9 +43,10 @@
#include "G4Event.hh"
#include "G4ParticleGun.hh"
#include "G4ParticleTable.hh"
#include "DicomGeometry.hh"
#include "RegularDicomDetectorConstruction.hh"
#include "G4ParticleDefinition.hh"
#include "Randomize.hh"
#include "CLHEP/Random/RandFlat.h"
DicomPrimaryGeneratorAction::DicomPrimaryGeneratorAction()
{
@@ -65,10 +66,11 @@ void DicomPrimaryGeneratorAction::GeneratePrimaries(G4Event *anEvent)
G4ParticleDefinition* particle
= particleTable->FindParticle(particleName="gamma");
particleGun->SetParticleDefinition(particle);
// ---- MGP ---- Numbers in the code should be replaced by const
particleGun->SetParticleMomentumDirection(G4ThreeVector(1.,0.*cm,0.*cm));
G4ThreeVector dir(2.*CLHEP::RandFlat::shoot()-1.,2.*CLHEP::RandFlat::shoot()-1.,2.*CLHEP::RandFlat::shoot()-1);
dir /= dir.mag();
particleGun->SetParticleMomentumDirection(dir);
particleGun->SetParticleEnergy(5.*MeV);
particleGun->SetParticlePosition(G4ThreeVector(0.,0.,0.));
particleGun->SetParticlePosition(G4ThreeVector(0.,0.,-20.)); // put it close to the patient voxels
particleGun->GeneratePrimaryVertex(anEvent);
}
@@ -0,0 +1,100 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// History:
// Pedro Arce
//
//*******************************************************
#include "globals.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4VPhysicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4PVParameterised.hh"
#include "NestedParamDicomDetectorConstruction.hh"
#include "DicomNestedPhantomParameterisation.hh"
NestedParamDicomDetectorConstruction::NestedParamDicomDetectorConstruction() : DicomDetectorConstruction()
{
}
NestedParamDicomDetectorConstruction::~NestedParamDicomDetectorConstruction()
{
}
//-------------------------------------------------------------
void NestedParamDicomDetectorConstruction::ConstructPatient()
{
#ifdef G4VERBOSE
G4cout << "NestedParamDicomDetectorConstruction::ConstructPatient " << G4endl;
#endif
//----- Replication of Water Phantom Volume.
//--- Y Slice
G4String yRepName("RepY");
G4VSolid* solYRep =
new G4Box(yRepName,nVoxelX*voxelHalfDimX,voxelHalfDimY,nVoxelZ*voxelHalfDimZ);
G4LogicalVolume* logYRep =
new G4LogicalVolume(solYRep,air,yRepName);
new G4PVReplica(yRepName,logYRep,container_logic,kYAxis,nVoxelY,voxelHalfDimY*2.);
//--- X Slice
G4String xRepName("RepX");
G4VSolid* solXRep =
new G4Box(xRepName,voxelHalfDimX,voxelHalfDimY,nVoxelZ*voxelHalfDimZ);
G4LogicalVolume* logXRep =
new G4LogicalVolume(solXRep,air,xRepName);
new G4PVReplica(xRepName,logXRep,logYRep,kXAxis,nVoxelX,voxelHalfDimX*2.);
//----- Voxel solid and logical volumes
//--- Z Slice
G4VSolid* solVoxel =
new G4Box("Patient",voxelHalfDimX,voxelHalfDimY,voxelHalfDimZ);
G4LogicalVolume* logicVoxel = new G4LogicalVolume(solVoxel,air,"Patient");
//
// Parameterisation for transformation of voxels.
// (voxel size is fixed in this example.
// e.g. nested parameterisation handles material and transfomation of voxels.)
G4ThreeVector voxelSize(voxelHalfDimX,voxelHalfDimY,voxelHalfDimZ);
DicomNestedPhantomParameterisation* param
= new DicomNestedPhantomParameterisation(voxelSize,fMaterials);
new G4PVParameterised("Patient", // their name
logicVoxel, // their logical volume
logXRep, // Mother logical volume
kXAxis, // Are placed along this axis
// kUndefined, // Are placed along this axis
nVoxelZ, // Number of cells
param); // Parameterisation.
param->SetMaterialIndices( fMateIDs );
param->SetNoVoxel( nVoxelX, nVoxelY, nVoxelZ );
}
@@ -0,0 +1,98 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// History:
// Pedro Arce
//
//*******************************************************
#include "globals.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4VPhysicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4PVParameterised.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4VisAttributes.hh"
#include "G4Colour.hh"
#include "G4ios.hh"
#include "RegularDicomDetectorConstruction.hh"
#include "DicomPhantomParameterisationColour.hh"
RegularDicomDetectorConstruction::RegularDicomDetectorConstruction() : DicomDetectorConstruction()
{
}
RegularDicomDetectorConstruction::~RegularDicomDetectorConstruction()
{
}
//-------------------------------------------------------------
void RegularDicomDetectorConstruction::ConstructPatient()
{
#ifdef G4VERBOSE
G4cout << "RegularDicomDetectorConstruction::ConstructPatient " << G4endl;
#endif
//----- Create parameterisation
DicomPhantomParameterisationColour* param = new DicomPhantomParameterisationColour();
//----- Set voxel dimensions
param->SetVoxelDimensions( voxelHalfDimX, voxelHalfDimY, voxelHalfDimZ );
//----- Set number of voxels
param->SetNoVoxel( nVoxelX, nVoxelY, nVoxelZ );
//----- Set list of materials
param->SetMaterials( fMaterials );
//----- Set list of material indices: for each voxel it is a number that correspond to the index of its material in the vector of materials defined above
param->SetMaterialIndices( fMateIDs );
//----- Define voxel logical volume
G4Box* voxel_solid = new G4Box( "Voxel", voxelHalfDimX, voxelHalfDimY, voxelHalfDimZ);
G4LogicalVolume* voxel_logic = new G4LogicalVolume(voxel_solid,fMaterials[0],"VoxelLogical",0,0,0); // material is not relevant, it will be changed by the ComputeMaterial method of the parameterisation
//--- Assign the container volume of the parameterisation
param->BuildContainerSolid(container_phys);
//--- Assure yourself that the voxels are completely filling the container volume
param->CheckVoxelsFillContainer( container_solid->GetXHalfLength(),
container_solid->GetYHalfLength(),
container_solid->GetZHalfLength() );
//----- The G4PVParameterised object that uses the created parameterisation should be placed in the container logical volume
G4PVParameterised * patient_phys = new G4PVParameterised("Patient",voxel_logic,container_logic,
kXAxis, nVoxelX*nVoxelY*nVoxelZ, param);
// if axis is set as kUndefined instead of kXAxis, GEANT4 will do an smart voxel optimisation (not needed if G4RegularNavigation is used)
//----- Set this physical volume as having a regular structure of type 1, so that G4RegularNavigation is used
patient_phys->SetRegularStructureId(1); // if not set, G4VoxelNavigation will be used instead
}
+9 -7
View File
@@ -1,10 +1,12 @@
/control/verbose 1
/run/verbose 1
/control/verbose 2
/run/verbose 2
#visualisation
/vis/scene/create
/vis/open OGLIX
/vis/viewer/zoom 3
/vis/viewer/set/viewpointThetaPhi 90 0
#/vis/viewer/update
#beamOn
/run/beamOn 3
/vis/viewer/update
/vis/viewer/zoom 5
/tracking/storeTrajectory 1
/vis/scene/endOfEventAction accumulate
/tracking/verbose 1
/run/beamOn 10