Import Geant4 11.2.0 source tree

This commit is contained in:
Gabriele Cosmo
2023-12-08 10:43:34 +01:00
parent dd1f179cda
commit 860a2b92bf
3962 changed files with 139318 additions and 164259 deletions
@@ -0,0 +1,199 @@
//******************************************************************************************
// BinToStd_GammaAtCreation.C
// Root command file
// Type: root BinToStd_GammaAtCreation.C
//
// Read the output file GammaAtCreation.dat that is generated by Geant4
// tomography simulation It read all the gamma at creation information, and
// rewrite the events in a binary file PixeEvent_std_AtCreation.DAT
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//*******************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
// Define a structure to read and write each event in the required binary format
struct PixeEvent
{
uint16_t energy_10eV;
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
struct ParticleInfo
{
float energy_keV;
float mx;
float my;
float mz;
};
struct RunInfo
{
// uint_16t
uint8_t projectionIndex; // 1 byte
uint16_t sliceIndex; //
uint16_t pixelIndex;
uint32_t nbParticle; // 4 bytes int
};
struct Point
{
double m_x;
double m_y;
double m_z;
};
// double DegreeToRadian(double degree) { return (PI * degree / 180.); }
bool IsDetected(Point poi1, Point poi2, double theta)
{
double a = (poi1.m_x * poi2.m_x + poi1.m_y * poi2.m_y + poi1.m_z * poi2.m_z)
/ sqrt(poi1.m_x * poi1.m_x + poi1.m_y * poi1.m_y + poi1.m_z * poi1.m_z)
/ sqrt(poi2.m_x * poi2.m_x + poi2.m_y * poi2.m_y + poi2.m_z * poi2.m_z);
if (a > 1.0) a = 1;
if (a < -1.0) a = -1;
double r = acos(a);
if (r > theta)
return false;
else
return true;
}
void BinToStd_GammaAtCreation()
{
//***********************************************************************
//**************************Detection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 10;
const int nbSlice = 1;
const int nbPixel = 20;
double totalAngleSpan = 180.; // in degree
double angleOfDetector = 135.; // angle of detector relative to the incident
// direction of the primary protons //
double distanceObjectDetector = 22.; // 22 mm
double radiusOfDetector = 5.; // 5 mm
// double theta = atan(radiusOfDetector/distanceObjectDetector); //half apex
// angle of the right circular cone in radian
double theta = 70 * TMath::DegToRad(); // in radian
//***********************************************************************
//**************************Detection parameters (end)*******************
//***********************************************************************
FILE* input = fopen("../build/GammaAtCreation.dat", "rb");
FILE* out = fopen("../build/PixeEvent_std_AtCreation.DAT", "wb");
if (input == NULL) {
printf("error for opening the input GammaAtCreation.dat file\n");
return;
}
RunInfo runInfo;
PixeEvent pixeEvent;
Point centerOfDetector;
Point gammaMomentum;
long long count = 0;
int runID = -1; // index of simulations, namely runID, starting from 0
// while(!feof(input)) //if not the end, read
while (fread(&runInfo, sizeof(RunInfo), 1, input)) {
runID++;
// if(runID==5) continue;
int nbParticle = runInfo.nbParticle;
//(begin)*****************************************************************
// the following codes are used only when in the simulation
// the index of projection, slice and pixel is not
// correctly configured
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
//(end)******************************************************************
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
printf(
"---------RunID=%d:\nProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d,"
"nbParticle = %d\n",
runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, nbParticle);
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
if (!nbParticle) continue;
std::vector<ParticleInfo> gammaAtCreation(nbParticle);
fread(&gammaAtCreation[0], sizeof(ParticleInfo), nbParticle, input);
// angleOfDetector+totalAngleSpan/nbProjection*runInfo.projectionIndex means
// the angle between source direction and detector, which should be constant
// when source is rotating
double ra = TMath::DegToRad()
* (angleOfDetector + totalAngleSpan / nbProjection * runInfo.projectionIndex);
centerOfDetector.m_x = distanceObjectDetector * cos(ra);
centerOfDetector.m_y = distanceObjectDetector * sin(ra);
centerOfDetector.m_z = 0;
for (int i = 0; i < nbParticle; ++i) {
// gamma selection: energy should be lower than 4095*10eV = 49.45 keV
if (gammaAtCreation[i].energy_keV >= 40.95 || gammaAtCreation[i].energy_keV <= 0.9)
continue; // gamma selection
gammaMomentum.m_x = gammaAtCreation[i].mx;
gammaMomentum.m_y = gammaAtCreation[i].my;
gammaMomentum.m_z = gammaAtCreation[i].mz;
if (!IsDetected(centerOfDetector, gammaMomentum, theta))
continue;
else {
pixeEvent.energy_10eV = floor(100 * gammaAtCreation[i].energy_keV + 0.5);
pixeEvent.projectionIndex = runInfo.projectionIndex;
pixeEvent.sliceIndex = runInfo.sliceIndex;
pixeEvent.pixelIndex = runInfo.pixelIndex;
fwrite(&pixeEvent, 7, 1, out);
count++;
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
// printf("momentum: (%f, %f, %f), energy: %f keV %d 10eV\n",
// gammaAtCreation[i].mx, gammaAtCreation[i].my, gammaAtCreation[i].mz,
// gammaAtCreation[i].energy_keV, pixeEvent.energy_10eV);
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
}
}
}
printf(
"---------------Number of PixeEvent in total: "
"%lld------------------------\n",
count);
fclose(input);
fclose(out);
// Recheck the output file in case
// FILE* input2 = fopen("PixeEvent_std_AtCreation.DAT","rb");
// PixeEvent p;
// while(fread(&p, 7, 1, input2))
// {
// printf("__ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d,
// Energy_10eV=%d\n", p.projectionIndex, p.sliceIndex, p.pixelIndex,
// p.energy_10eV);
// }
// fclose(input2);
}
@@ -0,0 +1,196 @@
//***********************************************************************************************************
// BinToStd_GammaAtExit.C
// Root command file
// Type: root BinToStd_GammaAtExit.C
//
// Read the output file ProtonAtExit.dat that is generated by Geant4 tomography
// simulation It read all the gamma at exit information, and rewrite the events
// in a binary file PixeEvent_std_AtExit.DAT
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
// Define a structure to read and write each event in the required binary format
struct PixeEvent
{
uint16_t energy_10eV;
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
struct ParticleInfo
{
float energy_keV;
float mx;
float my;
float mz;
};
struct RunInfo
{
// uint_16t
uint8_t projectionIndex; // 1 byte
uint16_t sliceIndex; //
uint16_t pixelIndex;
uint32_t nbParticle; // 4 bytes int
};
struct Point
{
double m_x;
double m_y;
double m_z;
};
bool IsDetected(Point poi1, Point poi2, double theta)
{
double a = (poi1.m_x * poi2.m_x + poi1.m_y * poi2.m_y + poi1.m_z * poi2.m_z)
/ sqrt(poi1.m_x * poi1.m_x + poi1.m_y * poi1.m_y + poi1.m_z * poi1.m_z)
/ sqrt(poi2.m_x * poi2.m_x + poi2.m_y * poi2.m_y + poi2.m_z * poi2.m_z);
if (a > 1.0) a = 1;
if (a < -1.0) a = -1;
double r = acos(a);
if (r > theta)
return false;
else
return true;
}
void BinToStd_GammaAtExit()
{
//***********************************************************************
//**************************Detection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 10;
const int nbSlice = 1;
const int nbPixel = 20;
double totalAngleSpan = 180.; // in degree
double angleOfDetector = 135.; // angle of detector relative to the incident
// direction of the primary protons //
double distanceObjectDetector = 22.; // 22 mm
double radiusOfDetector = 5.; // 5 mm
// double theta = atan(radiusOfDetector/distanceObjectDetector); //half apex
// angle of the right circular cone in radian
double theta = 70 * TMath::DegToRad(); // in radian
//***********************************************************************
//**************************Detection parameters (end)*******************
//***********************************************************************
FILE* input = fopen("../build/GammaAtExit.dat", "rb");
FILE* out = fopen("../build/PixeEvent_std_AtExit.DAT", "wb");
if (input == NULL) {
printf("error for opening the input GammaAtExit.dat file\n");
return;
}
RunInfo runInfo;
PixeEvent pixeEvent;
Point centerOfDetector;
Point gammaMomentum;
long long count = 0;
int runID = -1; // index of simulations, namely runID, starting from 0
// while(!feof(input)) //if not the end, read
while (fread(&runInfo, sizeof(RunInfo), 1, input)) {
runID++;
int nbParticle = runInfo.nbParticle;
// the following codes are used only when in the simulation
// ************(begin) the index of projection, slice and pixel is not
// correctly configured
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
//************************************************************************(end)
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
printf(
"---------RunID=%d:\nProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d,"
"nbParticle = %d\n",
runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, nbParticle);
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
if (!nbParticle) continue;
std::vector<ParticleInfo> gammaAtExit(nbParticle);
fread(&gammaAtExit[0], sizeof(ParticleInfo), nbParticle, input);
// angleOfDetector+totalAngleSpan/nbProjection*runInfo.projectionIndex means
// the angle between source direction and detector, which should be constant
// when source is rotating
double ra = TMath::DegToRad()
* (angleOfDetector + totalAngleSpan / nbProjection * runInfo.projectionIndex);
centerOfDetector.m_x = distanceObjectDetector * cos(ra);
centerOfDetector.m_y = distanceObjectDetector * sin(ra);
centerOfDetector.m_z = 0;
for (int i = 0; i < nbParticle; ++i) {
// gamma selection: energy should be lower than 4095*10eV = 49.45 keV
if (gammaAtExit[i].energy_keV >= 40.95 || gammaAtExit[i].energy_keV <= 0.9) continue;
gammaMomentum.m_x = gammaAtExit[i].mx;
gammaMomentum.m_y = gammaAtExit[i].my;
gammaMomentum.m_z = gammaAtExit[i].mz;
if (!IsDetected(centerOfDetector, gammaMomentum, theta))
continue;
else {
pixeEvent.energy_10eV = floor(100 * gammaAtExit[i].energy_keV + 0.5);
pixeEvent.projectionIndex = runInfo.projectionIndex;
pixeEvent.sliceIndex = runInfo.sliceIndex;
pixeEvent.pixelIndex = runInfo.pixelIndex;
fwrite(&pixeEvent, 7, 1, out);
count++;
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
// printf("momentum: (%f, %f, %f), energy: %f keV %d 10eV\n",
// gammaAtExit[i].mx, gammaAtExit[i].my, gammaAtExit[i].mz,
// gammaAtExit[i].energy_keV, pixeEvent.energy_10eV);
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
}
}
}
printf(
"\n---------------Number of PixeEvent in total: "
"%lld------------------------\n",
count);
fclose(input);
fclose(out);
// Recheck the output file in case
// FILE* input2;
// input2 = fopen("PixeEvent_std_AtExit.DAT","rb");
// PixeEvent p;
// while(fread(&p, 7, 1, input2))
// {
// printf("__ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d,
// Energy_10eV=%d\n", p.projectionIndex, p.sliceIndex, p.pixelIndex,
// p.energy_10eV);
// }
// fclose(input2);
}
@@ -0,0 +1,184 @@
//***********************************************************************************************************
// BinToStd_ProtonAtExit.C
// Root command file
// Type: root BinToStd_ProtonAtExit.C
//
// Read the output file ProtonAtExit.dat that is generated by Geant4 tomography simulation
// It reads proton at exit information, and rewrite the events in a binary file StimEvent_std.DAT
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
// Define a structure to read and write each event in the required binary format
struct StimEvent
{
uint16_t energy_keV; // different from Pixe Event, it is in keV
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
struct ParticleInfo
{
float energy_keV;
float mx;
float my;
float mz;
};
struct RunInfo
{
// uint_16t
uint8_t projectionIndex; // 1 byte
uint16_t sliceIndex; //
uint16_t pixelIndex;
uint32_t nbParticle; // 4 bytes int
};
struct Point
{
double m_x;
double m_y;
double m_z;
};
bool IsDetected(Point poi1, Point poi2, double theta)
{
double a = (poi1.m_x * poi2.m_x + poi1.m_y * poi2.m_y + poi1.m_z * poi2.m_z)
/ sqrt(poi1.m_x * poi1.m_x + poi1.m_y * poi1.m_y + poi1.m_z * poi1.m_z)
/ sqrt(poi2.m_x * poi2.m_x + poi2.m_y * poi2.m_y + poi2.m_z * poi2.m_z);
if (a > 1.0) a = 1;
if (a < -1.0) a = -1;
double r = acos(a);
if (r > theta)
return false;
else
return true;
}
void BinToStd_ProtonAtExit()
{
//***********************************************************************
//**************************Detection parameters (begin)****************
//***********************************************************************
const int nbProjection = 10;
const int nbSlice = 1;
const int nbPixel = 20;
double totalAngleSpan = 180.; // in degree
// angle of detector relative to the incident direction of the primary protons at first projection
// for proton, it is fixed to 0 degree, namely opposite to the source
double angleOfDetector = 0.;
double distanceObjectDetector = 22.; // 22 mm
double radiusOfDetector = 5.; // 5 mm
// double theta = atan(radiusOfDetector/distanceObjectDetector); //half apex angle of the right
// circular cone in radian
double theta = 10.2 * TMath::DegToRad(); // in radian
//***********************************************************************
//**************************Detection parameters (end)*******************
//***********************************************************************
FILE* input = fopen("../build/ProtonAtExit.dat", "rb");
FILE* out = fopen("../build/StimEvent_std.DAT", "wb");
if (input == NULL) {
printf("error for opening the input ProtonAtExit.dat file\n");
return;
}
RunInfo runInfo;
StimEvent stimEvent;
Point centerOfDetector;
Point protonMomentum;
long long count = 0;
int runID = -1;
// while(!feof(input)) //if not the end, read
while (fread(&runInfo, sizeof(RunInfo), 1, input)) {
runID++;
int nbParticle = runInfo.nbParticle;
//(begin)***************************************************************
// the following codes are used only when in the simulation
// the index of projection, slice and pixel is not
// correctly configured
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
//(end)******************************************************************
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
printf("---------RunID=%d: ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, nbParticle = %d\n",
runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, nbParticle);
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
if (!nbParticle) continue;
std::vector<ParticleInfo> protonAtExit(nbParticle);
fread(&protonAtExit[0], sizeof(ParticleInfo), nbParticle, input);
// angleOfDetector+totalAngleSpan/nbProjection*runInfo.projectionIndex means the angle between
// source direction and detector, which should be constant when source is rotating
double ra = TMath::DegToRad()
* (angleOfDetector + totalAngleSpan / nbProjection * runInfo.projectionIndex);
centerOfDetector.m_x = distanceObjectDetector * cos(ra);
centerOfDetector.m_y = distanceObjectDetector * sin(ra);
centerOfDetector.m_z = 0;
for (int i = 0; i < nbParticle; ++i) {
// proton selection: energy should be lower than 4095 keV
if (protonAtExit[i].energy_keV >= 4095) continue; // proton selection
protonMomentum.m_x = protonAtExit[i].mx;
protonMomentum.m_y = protonAtExit[i].my;
protonMomentum.m_z = protonAtExit[i].mz;
if (!IsDetected(centerOfDetector, protonMomentum, theta))
continue;
else {
stimEvent.energy_keV = floor(protonAtExit[i].energy_keV + 0.5);
stimEvent.projectionIndex = runInfo.projectionIndex;
stimEvent.sliceIndex = runInfo.sliceIndex;
stimEvent.pixelIndex = runInfo.pixelIndex;
fwrite(&stimEvent, 7, 1, out);
count++;
// printf("energy=%f keV\n",protonAtExit[i].energy_keV);
}
}
}
printf("---------------Number of StimEvent in total: %lld------------------------\n", count);
fclose(input);
fclose(out);
// FILE* input2;
// input2 = fopen("StimEvent_std.DAT","rb");
// StimEvent p;
// double eventId = -1;
// while(fread(&p, 7, 1, input2))
// {
// if(p.projectionIndex == 8 &&p.sliceIndex ==64 && p.pixelIndex==64)
// {
// eventId++;
// printf("StimEvent_%.0f ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, Energy_keV=%d keV\n",
// eventId, p.projectionIndex, p.sliceIndex, p.pixelIndex, p.energy_keV);
// }
// }
// fclose(input2);
}
@@ -0,0 +1,296 @@
//***********************************************************************************************************
// BinToStd_gamma_position.C
// Root command file
// Type: root BinToStd_gamma_position.C
//
// Read the X-ray output file that is generated by Geant4 tomography
// simulation. It reads gamma information, either at creation, or at exit, and rewrite the events
// in a binary file PixeEvent_std.DAT
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
bool IsEqual(double a, double b, double eps, double releps)
{
if (a == b) {
return true;
}
if (fabs(a - b) <= releps * fabs(b)) {
return true;
}
if (fabs(a - b) < eps) {
return true;
}
return false;
}
double eps = 1e-20; // absolut difference
double releps = 1e-10; // relative difference
// Define a structure to read and write each event in the required binary format
struct PixeEvent
{
uint16_t energy_10eV;
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
struct ParticleInfo
{
float energy_keV;
float mx;
float my;
float mz;
float x;
float y;
float z;
};
struct RunInfo
{
// uint_16t
uint8_t projectionIndex; // 1 byte
uint16_t sliceIndex; //
uint16_t pixelIndex;
uint32_t nbParticle; // 4 bytes int
};
struct Point
{
double m_x;
double m_y;
double m_z;
};
bool IsDetected(Point poi1, Point poi2, double theta)
{
double a = (poi1.m_x * poi2.m_x + poi1.m_y * poi2.m_y + poi1.m_z * poi2.m_z)
/ sqrt(poi1.m_x * poi1.m_x + poi1.m_y * poi1.m_y + poi1.m_z * poi1.m_z)
/ sqrt(poi2.m_x * poi2.m_x + poi2.m_y * poi2.m_y + poi2.m_z * poi2.m_z);
if (a > 1.0) a = 1;
if (a < -1.0) a = -1;
double r = acos(a);
if (r > theta)
return false;
else {
// printf(" acos: %f, radius: %f\n", r, theta);
return true;
}
}
bool IsDetected_position(Point poi1, Point poi2, double r)
{
double a = sqrt((poi1.m_x - poi2.m_x) * (poi1.m_x - poi2.m_x)
+ (poi1.m_y - poi2.m_y) * (poi1.m_y - poi2.m_y)
+ (poi1.m_z - poi2.m_z) * (poi1.m_z - poi2.m_z));
// if(a <= r) return true;
if (a > r)
return false;
else {
// printf(" distance of two points: %f, radius: %f\n", a, r);
return true;
}
}
void BinToStd_gamma_position()
{
//***********************************************************************
//**************************Detection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 1;
const int nbSlice = 1;
const int nbPixel = 1;
double totalAngleSpan = 180.; // in degree
double angleOfDetector = 135.; // angle of detector relative to the incident
double distanceObjectDetector = 22000.; // um
// double theta = atan(radiusOfDetector/distanceObjectDetector); //half apex
// angle of the right circular cone in radian
double theta = 14.726 * TMath::DegToRad(); // in radian
double radiusOfDetector = distanceObjectDetector * tan(theta);
bool usePosition = true;
//***********************************************************************
//**************************Detection parameters (end)*******************
//***********************************************************************
FILE* input = fopen("../build/GammaAtExit.dat", "rb");
FILE* out = fopen("../build/PixeEvent_std_AtExit.DAT", "wb");
if (input == NULL) {
printf("error for opening the input file\n");
return;
}
RunInfo runInfo;
PixeEvent pixeEvent;
Point centerOfDetector;
Point gammaMomentum;
Point gammaPosition;
Point intersectionPoint;
long long count = 0;
int runID = -1; // index of simulations, namely runID, starting from 0
// while(!feof(input)) //if not the end, read
while (fread(&runInfo, sizeof(RunInfo), 1, input)) {
runID++;
int nbParticle = runInfo.nbParticle;
//(begin)****************************************************************
// the following codes are used only when in the simulation
// the index of projection, slice and pixel is not
// correctly configured
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
//(end)******************************************************************
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
printf(
"---------RunID=%d:\nProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d,"
"nbParticle = %d\n",
runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, nbParticle);
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
if (!nbParticle) continue;
std::vector<ParticleInfo> gammaAtExit(nbParticle);
fread(&gammaAtExit[0], sizeof(ParticleInfo), nbParticle, input);
// angleOfDetector+totalAngleSpan/nbProjection*runInfo.projectionIndex means
// the angle between source direction and detector, which should be constant
// when source is rotating
double ra = TMath::DegToRad()
* (angleOfDetector + totalAngleSpan / nbProjection * runInfo.projectionIndex);
centerOfDetector.m_x = distanceObjectDetector * cos(ra);
centerOfDetector.m_y = distanceObjectDetector * sin(ra);
centerOfDetector.m_z = 0;
for (int i = 0; i < nbParticle; ++i) {
// gamma selection: energy should be lower than 4095*10eV = 49.45 keV
if (gammaAtExit[i].energy_keV >= 40.95 || gammaAtExit[i].energy_keV <= 0.9) continue;
gammaMomentum.m_x = gammaAtExit[i].mx;
gammaMomentum.m_y = gammaAtExit[i].my;
gammaMomentum.m_z = gammaAtExit[i].mz;
if (!usePosition) {
if (!IsDetected(centerOfDetector, gammaMomentum, theta)) continue;
}
else {
double c =
distanceObjectDetector * (gammaMomentum.m_x * cos(ra) + gammaMomentum.m_y * sin(ra));
if (IsEqual(0, c, eps, releps)) continue; // parallel
gammaPosition.m_x = gammaAtExit[i].x;
gammaPosition.m_y = gammaAtExit[i].y;
gammaPosition.m_z = gammaAtExit[i].z;
double t = (distanceObjectDetector * distanceObjectDetector
- gammaPosition.m_x * distanceObjectDetector * cos(ra)
- gammaPosition.m_y * distanceObjectDetector * sin(ra))
/ c;
intersectionPoint.m_x = gammaPosition.m_x + gammaMomentum.m_x * t;
intersectionPoint.m_y = gammaPosition.m_y + gammaMomentum.m_y * t;
intersectionPoint.m_z = gammaPosition.m_z + gammaMomentum.m_z * t;
if (!IsDetected_position(centerOfDetector, intersectionPoint, radiusOfDetector)) continue;
// printf(" t = %f, intersection point: (%f, %f, %f) centor of detector: (%f, %f, %f)
// 111=%f, 222=%f \n", t, intersectionPoint.m_x,intersectionPoint.m_y,intersectionPoint.m_z,
// centerOfDetector.m_x,centerOfDetector.m_y,centerOfDetector.m_z,
// (distanceObjectDetector*distanceObjectDetector-gammaPosition.m_x*distanceObjectDetector*cos(ra)
// -gammaPosition.m_y*distanceObjectDetector*sin(ra)), c);
// printf(" distanceObjectDetector = %f, gammaPosition.m_x=%f,
// distanceObjectDetector*cos(ra)=%f, gammaPosition.m_y=%f,
// distanceObjectDetector*sin(ra)=%f\n", distanceObjectDetector, gammaPosition.m_x,
// distanceObjectDetector*cos(ra),
// gammaPosition.m_y,
// distanceObjectDetector*sin(ra));
double tt = (intersectionPoint.m_x - gammaPosition.m_x) * gammaMomentum.m_x
+ (intersectionPoint.m_y - gammaPosition.m_y) * gammaMomentum.m_y
+ (intersectionPoint.m_z - gammaPosition.m_z) * gammaMomentum.m_z;
if (tt < 0) continue;
}
pixeEvent.energy_10eV = floor(100 * gammaAtExit[i].energy_keV + 0.5);
pixeEvent.projectionIndex = runInfo.projectionIndex;
pixeEvent.sliceIndex = runInfo.sliceIndex;
pixeEvent.pixelIndex = runInfo.pixelIndex;
fwrite(&pixeEvent, 7, 1, out);
count++;
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
if (!usePosition) {
printf(
"---------id = %d, RunID=%d ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, momentum: "
"(%f, %f, %f), energy: %f keV\n",
i, runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex,
gammaAtExit[i].mx, gammaAtExit[i].my, gammaAtExit[i].mz, gammaAtExit[i].energy_keV);
}
else {
// printf("---------id = %d, RunID=%d ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d,
// momentum: (%f, %f, %f), energy: %f keV, position: (%f, %f, %f)\n", i, runID,
// runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, gammaAtExit[i].mx,
// gammaAtExit[i].my, gammaAtExit[i].mz, gammaAtExit[i].energy_keV, gammaAtExit[i].x,
// gammaAtExit[i].y, gammaAtExit[i].z);
printf(
"---------id = %d, RunID=%d ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, momentum: "
"(%f, %f, %f), energy: %f keV\n",
i, runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex,
gammaAtExit[i].mx, gammaAtExit[i].my, gammaAtExit[i].mz, gammaAtExit[i].energy_keV);
}
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
}
}
printf(
"\n---------------Number of PixeEvent in total: "
"%lld------------------------\n",
count);
fclose(input);
fclose(out);
// Recheck the output file in case
// FILE* input2;
// input2 = fopen("PixeEvent_std_AtExit.DAT","rb");
// PixeEvent p;
// while(fread(&p, 7, 1, input2))
// {
// printf("__ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d,
// Energy_10eV=%d\n", p.projectionIndex, p.sliceIndex, p.pixelIndex,
// p.energy_10eV);
// }
// fclose(input2);
}
@@ -0,0 +1,305 @@
//***********************************************************************************************************
// BinToStd_proton_position.C
// Root command file
// Type: root BinToStd_proton_position.C
//
// Read the X-ray output file that is generated by Geant4 tomography
// simulation. It reads gamma information, either at creation, or at exit, and rewrite the events
// in a binary file StimEvent_std.DAT
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
bool IsEqual(double a, double b, double eps, double releps)
{
if (a == b) {
return true;
}
if (fabs(a - b) <= releps * fabs(b)) {
return true;
}
if (fabs(a - b) < eps) {
return true;
}
return false;
}
double eps = 1e-20; // absolut difference
double releps = 1e-10; // relative difference
// Define a structure to read and write each event in the required binary format
struct StimEvent
{
uint16_t energy_keV; // different from Pixe Event, it is in keV
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
struct ParticleInfo
{
float energy_keV;
float mx;
float my;
float mz;
float x;
float y;
float z;
};
struct RunInfo
{
// uint_16t
uint8_t projectionIndex; // 1 byte
uint16_t sliceIndex; //
uint16_t pixelIndex;
uint32_t nbParticle; // 4 bytes int
};
struct Point
{
double m_x;
double m_y;
double m_z;
};
bool IsDetected(Point poi1, Point poi2, double theta)
{
double a = (poi1.m_x * poi2.m_x + poi1.m_y * poi2.m_y + poi1.m_z * poi2.m_z)
/ sqrt(poi1.m_x * poi1.m_x + poi1.m_y * poi1.m_y + poi1.m_z * poi1.m_z)
/ sqrt(poi2.m_x * poi2.m_x + poi2.m_y * poi2.m_y + poi2.m_z * poi2.m_z);
if (a > 1.0) a = 1;
if (a < -1.0) a = -1;
double r = acos(a);
if (r > theta)
return false;
else {
// printf(" acos: %f, radius: %f\n", r, theta);
return true;
}
}
bool IsDetected_position(Point poi1, Point poi2, double r)
{
double a = sqrt((poi1.m_x - poi2.m_x) * (poi1.m_x - poi2.m_x)
+ (poi1.m_y - poi2.m_y) * (poi1.m_y - poi2.m_y)
+ (poi1.m_z - poi2.m_z) * (poi1.m_z - poi2.m_z));
// if(a <= r) return true;
if (a > r)
return false;
else {
// printf(" distance of two points: %f, radius: %f\n", a, r);
return true;
}
}
void BinToStd_proton_position()
{
// printf("%f %f %f\n", acos(1), acos(-1), acos(0));
// return;
//***********************************************************************
//**************************Detection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 1;
const int nbSlice = 1;
const int nbPixel = 1;
double totalAngleSpan = 180.; // in degree
double angleOfDetector = 0.; // angle of detector relative to the incident
double distanceObjectDetector = 22000.; // um
// double theta = atan(radiusOfDetector/distanceObjectDetector); //half apex
// angle of the right circular cone in radian
double theta = 10.2 * TMath::DegToRad(); // in radian
double radiusOfDetector = distanceObjectDetector * tan(theta);
bool usePosition = true;
//***********************************************************************
//**************************Detection parameters (end)*******************
//***********************************************************************
FILE* input = fopen("../build/ProtonAtExit.dat", "rb");
FILE* out = fopen("../build/StimEvent_std", "wb");
if (input == NULL) {
printf("error for opening the input file\n");
return;
}
RunInfo runInfo;
StimEvent stimEvent;
Point centerOfDetector;
Point protonMomentum;
Point protonPosition;
Point intersectionPoint;
long long count = 0;
int runID = -1; // index of simulations, namely runID, starting from 0
// while(!feof(input)) //if not the end, read
while (fread(&runInfo, sizeof(RunInfo), 1, input)) {
runID++;
int nbParticle = runInfo.nbParticle;
//(begin)****************************************************************
// the following codes are used only when in the simulation
// the index of projection, slice and pixel is not
// correctly configured
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
//(end)*******************************************************************
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
printf(
"---------RunID=%d:\nProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d,"
"nbParticle = %d\n",
runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, nbParticle);
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
if (!nbParticle) continue;
std::vector<ParticleInfo> protonAtExit(nbParticle);
fread(&protonAtExit[0], sizeof(ParticleInfo), nbParticle, input);
// angleOfDetector+totalAngleSpan/nbProjection*runInfo.projectionIndex means
// the angle between source direction and detector, which should be constant
// when source is rotating
double ra = TMath::DegToRad()
* (angleOfDetector + totalAngleSpan / nbProjection * runInfo.projectionIndex);
centerOfDetector.m_x = distanceObjectDetector * cos(ra);
centerOfDetector.m_y = distanceObjectDetector * sin(ra);
centerOfDetector.m_z = 0;
for (int i = 0; i < nbParticle; ++i) {
// proton selection: energy should be lower than 4095 keV
if (protonAtExit[i].energy_keV >= 4095) continue;
protonMomentum.m_x = protonAtExit[i].mx;
protonMomentum.m_y = protonAtExit[i].my;
protonMomentum.m_z = protonAtExit[i].mz;
if (!usePosition) {
if (!IsDetected(centerOfDetector, protonMomentum, theta)) continue;
}
else {
double c =
distanceObjectDetector * (protonMomentum.m_x * cos(ra) + protonMomentum.m_y * sin(ra));
if (IsEqual(0, c, eps, releps)) continue; // parallel
protonPosition.m_x = protonAtExit[i].x;
protonPosition.m_y = protonAtExit[i].y;
protonPosition.m_z = protonAtExit[i].z;
double t = (distanceObjectDetector * distanceObjectDetector
- protonPosition.m_x * distanceObjectDetector * cos(ra)
- protonPosition.m_y * distanceObjectDetector * sin(ra))
/ c;
intersectionPoint.m_x = protonPosition.m_x + protonMomentum.m_x * t;
intersectionPoint.m_y = protonPosition.m_y + protonMomentum.m_y * t;
intersectionPoint.m_z = protonPosition.m_z + protonMomentum.m_z * t;
if (!IsDetected_position(centerOfDetector, intersectionPoint, radiusOfDetector)) continue;
// printf(" t = %f, intersection point: (%f, %f, %f) centor of detector: (%f, %f, %f)
// 111=%f, 222=%f \n", t, intersectionPoint.m_x,intersectionPoint.m_y,intersectionPoint.m_z,
// centerOfDetector.m_x,centerOfDetector.m_y,centerOfDetector.m_z,
// (distanceObjectDetector*distanceObjectDetector-protonPosition.m_x*distanceObjectDetector*cos(ra)
// -protonPosition.m_y*distanceObjectDetector*sin(ra)), c);
// printf(" distanceObjectDetector = %f, protonPosition.m_x=%f,
// distanceObjectDetector*cos(ra)=%f, protonPosition.m_y=%f,
// distanceObjectDetector*sin(ra)=%f\n", distanceObjectDetector, protonPosition.m_x,
// distanceObjectDetector*cos(ra),
// protonPosition.m_y,
// distanceObjectDetector*sin(ra));
double tt = (intersectionPoint.m_x - protonPosition.m_x) * protonMomentum.m_x
+ (intersectionPoint.m_y - protonPosition.m_y) * protonMomentum.m_y
+ (intersectionPoint.m_z - protonPosition.m_z) * protonMomentum.m_z;
if (tt < 0) continue;
}
stimEvent.energy_10eV = floor(100 * protonAtExit[i].energy_keV + 0.5);
stimEvent.projectionIndex = runInfo.projectionIndex;
stimEvent.sliceIndex = runInfo.sliceIndex;
stimEvent.pixelIndex = runInfo.pixelIndex;
fwrite(&stimEvent, 7, 1, out);
count++;
//***********************************************************************
//**************************Print information
//(begin)********************
//***********************************************************************
if (!usePosition) {
printf(
"---------id = %d, RunID=%d ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, momentum: "
"(%f, %f, %f), energy: %f keV\n",
i, runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex,
protonAtExit[i].mx, protonAtExit[i].my, protonAtExit[i].mz, protonAtExit[i].energy_keV);
}
else {
// printf("---------id = %d, RunID=%d ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d,
// momentum: (%f, %f, %f), energy: %f keV, position: (%f, %f, %f)\n", i, runID,
// runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, protonAtExit[i].mx,
// protonAtExit[i].my, protonAtExit[i].mz, protonAtExit[i].energy_keV, protonAtExit[i].x,
// protonAtExit[i].y, protonAtExit[i].z);
printf(
"---------id = %d, RunID=%d ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, momentum: "
"(%f, %f, %f), energy: %f keV\n",
i, runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex,
protonAtExit[i].mx, protonAtExit[i].my, protonAtExit[i].mz, protonAtExit[i].energy_keV);
}
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
}
}
printf(
"\n---------------Number of StimEvent in total: "
"%lld------------------------\n",
count);
fclose(input);
fclose(out);
// FILE* input2;
// input2 = fopen("StimEvent_std.DAT","rb");
// StimEvent p;
// double eventId = -1;
// while(fread(&p, 7, 1, input2))
// {
// if(p.projectionIndex == 8 &&p.sliceIndex ==64 && p.pixelIndex==64)
// {
// eventId++;
// printf("StimEvent_%.0f ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, Energy_keV=%d keV\n",
// eventId, p.projectionIndex, p.sliceIndex, p.pixelIndex, p.energy_keV);
// }
// }
// fclose(input2);
}
@@ -0,0 +1,85 @@
//***********************************************************************************************************
// Check_PixeEventFile.C
// Root command file
// Use it by typing in the command line of Root terminal: root Check_PixeEventFile.C
//
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
#define PI 3.14159265f
// Define a structure to read and write each event in the required binary format
struct PixeEvent
{
uint16_t energy_10eV;
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
struct ParticleInfo
{
float energy_keV;
float mx;
float my;
float mz;
};
struct RunInfo
{
// uint_16t
uint8_t projectionIndex; // 1 byte
uint16_t sliceIndex; //
uint16_t pixelIndex;
uint32_t nbParticle; // 4 bytes int
};
double DegreeToRadian(double degree)
{
return (PI * degree / 180.);
}
struct Point
{
double m_x;
double m_y;
double m_z;
};
bool IsDetected(Point poi1, Point poi2, double theta)
{
double a = (poi1.m_x * poi2.m_x + poi1.m_y * poi2.m_y + poi1.m_z * poi2.m_z)
/ sqrt(poi1.m_x * poi1.m_x + poi1.m_y * poi1.m_y + poi1.m_z * poi1.m_z)
/ sqrt(poi2.m_x * poi2.m_x + poi2.m_y * poi2.m_y + poi2.m_z * poi2.m_z);
if (a > 1.0) a = 1;
if (a < -1.0) a = -1;
double r = acos(a);
if (r > theta)
return false;
else
return true;
}
void Check_PixeEventFile()
{
FILE* input2 =
fopen("../build/PixeEvent_std_AtExit_Detector135_Aperture70_50Projections.DAT", "rb");
PixeEvent ppp;
int proj = -1;
while (fread(&ppp, 7, 1, input2)) {
if (ppp.projectionIndex != proj) {
printf("__ProjectionIndex=%d\n", ppp.projectionIndex);
proj = ppp.projectionIndex;
}
// printf("__ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, Energy_10eV=%d\n",
// ppp.projectionIndex, ppp.sliceIndex, ppp.pixelIndex, ppp.energy_10eV);
}
fclose(input2);
}
@@ -0,0 +1,279 @@
//***********************************************************************************************************
// Concatenate_BinToStd_GammaAtCreation.C
// Root command file
// Type: root Concatenate_BinToStd_GammaAtCreation.C
//
// It is used in case of interruption
// Read 2 output files GammaAtCreation_1.dat and GammaAtCreation_2.dat that are generated by Geant4
// tomography simulation. It reads all the gamma at creation information, and rewrite the events in
// a binary file PixeEvent_std_AtCreation.DAT
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
// Define a structure to read and write each event in the required binary format
struct PixeEvent
{
uint16_t energy_10eV;
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
struct ParticleInfo
{
float energy_keV;
float mx;
float my;
float mz;
};
struct RunInfo
{
// uint_16t
uint8_t projectionIndex; // 1 byte
uint16_t sliceIndex; //
uint16_t pixelIndex;
uint32_t nbParticle; // 4 bytes int
};
struct Point
{
double m_x;
double m_y;
double m_z;
};
bool IsDetected(Point poi1, Point poi2, double theta)
{
double a = (poi1.m_x * poi2.m_x + poi1.m_y * poi2.m_y + poi1.m_z * poi2.m_z)
/ sqrt(poi1.m_x * poi1.m_x + poi1.m_y * poi1.m_y + poi1.m_z * poi1.m_z)
/ sqrt(poi2.m_x * poi2.m_x + poi2.m_y * poi2.m_y + poi2.m_z * poi2.m_z);
if (a > 1.0) a = 1;
if (a < -1.0) a = -1;
double r = acos(a);
if (r > theta)
return false;
else
return true;
}
void Concatenate_BinToStd_GammaAtCreation()
{
//***********************************************************************
//**************************Detection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 10;
const int nbSlice = 1;
const int nbPixel = 20;
double totalAngleSpan = 180.; // in degree
double angleOfDetector =
135.; // angle of detector relative to the incident direction of the primary protons //
double distanceObjectDetector = 22.; // 22 mm
double radiusOfDetector = 5.; // 5 mm
// double theta = atan(radiusOfDetector/distanceObjectDetector); //half apex angle of the right
// circular cone in radian
double theta = 70 * TMath::DegToRad(); // in radian
int P_interrupt = 6; // Projection of interruption
//***********************************************************************
//**************************Detection parameters (end)*******************
//***********************************************************************
// assuming there is one interruption
FILE* input1 = fopen("../build/GammaAtCreation_1.dat", "rb");
FILE* input2 = fopen("../build/GammaAtCreation_2.dat", "rb");
FILE* out = fopen("../build/PixeEvent_std_AtCreation.DAT", "wb");
if (input1 == NULL) {
printf("error for opening the input GammaAtCreation_1.dat file\n");
return;
}
if (input2 == NULL) {
printf("error for opening the input GammaAtCreation_2.dat file\n");
return;
}
RunInfo runInfo;
PixeEvent pixeEvent;
Point centerOfDetector;
Point gammaMomentum;
long long count1 = 0;
long long count2 = 0;
int runID = -1; // index of simulations, namely runID, starting from 0
// ************************************************************(begin)
// **********************READ FIRST FILE***********************
// ************************************************************
while (fread(&runInfo, sizeof(RunInfo), 1, input1)) {
runID++;
//(begin)***************************************************************
// the following codes are used only when in the simulation
// the index of projection, slice and pixel is not
// correctly configured
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
//(end)******************************************************************
if (runInfo.projectionIndex == P_interrupt) {
runID--;
break;
}
int nbParticle = runInfo.nbParticle;
std::vector<ParticleInfo> gammaAtCreation(nbParticle);
fread(&gammaAtCreation[0], sizeof(ParticleInfo), nbParticle, input1);
// if(runInfo.sliceIndex!=1) continue;
// if(runInfo.sliceIndex!=31&&runInfo.sliceIndex!=32) continue;
// if(runInfo.sliceIndex!=31) continue;
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
printf("-1--runId %d, ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, nbParticle = %d\n",
runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, nbParticle);
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
// angleOfDetector+totalAngleSpan/nbProjection*runInfo.projectionIndex means the angle between
// source direction and detector, which should be constant when source is rotating
double ra = TMath::DegToRad()
* (angleOfDetector + totalAngleSpan / nbProjection * runInfo.projectionIndex);
centerOfDetector.m_x = distanceObjectDetector * cos(ra);
centerOfDetector.m_y = distanceObjectDetector * sin(ra);
centerOfDetector.m_z = 0;
for (int i = 0; i < nbParticle; ++i) {
// gamma selection: energy should be lower than 4095*10eV = 49.45 keV
if (gammaAtCreation[i].energy_keV >= 40.95 || gammaAtCreation[i].energy_keV <= 0.9)
continue; // gamma selection
gammaMomentum.m_x = gammaAtCreation[i].mx;
gammaMomentum.m_y = gammaAtCreation[i].my;
gammaMomentum.m_z = gammaAtCreation[i].mz;
if (!IsDetected(centerOfDetector, gammaMomentum, theta))
continue;
else {
pixeEvent.energy_10eV = floor(100 * gammaAtCreation[i].energy_keV + 0.5);
pixeEvent.projectionIndex = runInfo.projectionIndex;
pixeEvent.sliceIndex = runInfo.sliceIndex;
pixeEvent.pixelIndex = runInfo.pixelIndex;
fwrite(&pixeEvent, 7, 1, out);
count1++;
}
}
}
printf("---------------Number of PixeEvent in the first file: %lld------------------------\n",
count1);
fclose(input1);
// ************************************************************
// **********************READ FIRST FILE (end)*****************
// ************************************************************
// ************************************************************
// **********************READ SECOND FILE (begin)**************
// ************************************************************
while (fread(&runInfo, sizeof(RunInfo), 1, input2)) {
runID++;
//(begin)***************************************************************
// the following codes are used only when in the simulation
// the index of projection, slice and pixel is not
// correctly configured
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
//(end)******************************************************************
int nbParticle = runInfo.nbParticle;
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
printf("-2--runId %d, ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, nbParticle = %d\n",
runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, nbParticle);
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
if (!nbParticle) continue;
std::vector<ParticleInfo> gammaAtCreation(nbParticle);
fread(&gammaAtCreation[0], sizeof(ParticleInfo), nbParticle, input2);
// if(runInfo.sliceIndex!=1) continue;
// if(runInfo.sliceIndex!=31) continue;
// if(runInfo.sliceIndex!=31&&runInfo.sliceIndex!=32) continue;
// angleOfDetector+totalAngleSpan/nbProjection*runInfo.projectionIndex means the angle between
// source direction and detector, which should be constant when source is rotating
double ra = TMath::DegToRad()
* (angleOfDetector + totalAngleSpan / nbProjection * runInfo.projectionIndex);
centerOfDetector.m_x = distanceObjectDetector * cos(ra);
centerOfDetector.m_y = distanceObjectDetector * sin(ra);
centerOfDetector.m_z = 0;
for (int i = 0; i < nbParticle; ++i) {
// gamma selection: energy should be lower than 4095*10eV = 49.45 keV
if (gammaAtCreation[i].energy_keV >= 40.95 || gammaAtCreation[i].energy_keV <= 0.9)
continue; // gamma selection
gammaMomentum.m_x = gammaAtCreation[i].mx;
gammaMomentum.m_y = gammaAtCreation[i].my;
gammaMomentum.m_z = gammaAtCreation[i].mz;
if (!IsDetected(centerOfDetector, gammaMomentum, theta))
continue;
else {
pixeEvent.energy_10eV = floor(100 * gammaAtCreation[i].energy_keV + 0.5);
pixeEvent.projectionIndex = runInfo.projectionIndex;
pixeEvent.sliceIndex = runInfo.sliceIndex;
pixeEvent.pixelIndex = runInfo.pixelIndex;
fwrite(&pixeEvent, 7, 1, out);
count2++;
}
}
}
printf("---------------Number of PixeEvent in in the second file: %lld------------------------\n",
count2);
// ************************************************************
// **********************READ SECOND FILE (end)****************
// ************************************************************
printf("---------------Number of PixeEvent in total: %lld------------------------\n",
count1 + count2);
fclose(input2);
fclose(out);
// Recheck the output file in case
// FILE* input2 = fopen("PixeEvent_std_AtCreation.DAT","rb");
// PixeEvent p;
// while(fread(&p, 7, 1, input2))
// {
// printf("__ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, Energy_10eV=%d\n",
// p.projectionIndex, p.sliceIndex, p.pixelIndex, p.energy_10eV);
// }
// fclose(input2);
}
@@ -0,0 +1,226 @@
//***********************************************************************************************************
// Concatenate_BinToStd_GammaAtCreation_fabricate.C
// Root command file
// Use it by typing in the command line of Root terminal: root
// Concatenate_BinToStd_GammaAtCreation_fabricate.C
//
//
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
#define PI 3.14159265f
// Define a structure to read and write each event in the required binary format
struct PixeEvent
{
uint16_t energy_10eV;
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
struct ParticleInfo
{
float energy_keV;
float mx;
float my;
float mz;
};
struct RunInfo
{
// uint_16t
uint8_t projectionIndex; // 1 byte
uint16_t sliceIndex; //
uint16_t pixelIndex;
uint32_t nbParticle; // 4 bytes int
};
double DegreeToRadian(double degree)
{
return (PI * degree / 180.);
}
struct Point
{
double m_x;
double m_y;
double m_z;
};
bool IsDetected(Point poi1, Point poi2, double theta)
{
double a = (poi1.m_x * poi2.m_x + poi1.m_y * poi2.m_y + poi1.m_z * poi2.m_z)
/ sqrt(poi1.m_x * poi1.m_x + poi1.m_y * poi1.m_y + poi1.m_z * poi1.m_z)
/ sqrt(poi2.m_x * poi2.m_x + poi2.m_y * poi2.m_y + poi2.m_z * poi2.m_z);
if (a > 1.0) a = 1;
if (a < -1.0) a = -1;
double r = acos(a);
if (r > theta)
return false;
else
return true;
}
void Concatenate_BinToStd_GammaAtCreation_fabricate()
{
//***********************************************************************
//**************************Detection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 100;
const int nbSlice = 1;
const int nbPixel = 128;
double totalAngleSpan = 180.; // in degree
double angleOfDetector =
135.; // angle of detector relative to the incident direction of the primary protons //
double distanceObjectDetector = 22.; // 22 mm
double radiusOfDetector = 5.; // 5 mm
// double theta = atan(radiusOfDetector/distanceObjectDetector); //half apex angle of the right
// circular cone in radian double theta = 14.726*TMath::DegToRad(); // in radian
double theta = 70 * TMath::DegToRad(); // in radian
// double theta = 70*TMath::DegToRad(); // in radian
// double theta = DegreeToRadian(70);
int P_interrupt = 1; // Projection of interruption
//***********************************************************************
//**************************Detection parameters (end)*******************
//***********************************************************************
// assuming there is one interruption
FILE* input1 = fopen("../RT7_GDP_1Projs_1Slice_128Pixels_2000000_4MeV/GammaAtCreation.dat", "rb");
FILE* out =
fopen("../RT7_GDP_1Projs_1Slice_128Pixels_2000000_4MeV/PixeEvent_std_AtCreation.DAT", "wb");
// FILE* temp;
// temp =fopen("temp.DAT","wb");
if (input1 == NULL) {
printf("error for opening the input GammaAtCreation.dat file\n");
return;
}
RunInfo runInfo;
PixeEvent pixeEvent;
Point centerOfDetector;
Point gammaMomentum;
long long count1 = 0;
long long count2 = 0;
int runID = -1; // index of simulations, namely runID, starting from 0
std::vector<PixeEvent> eventVec;
// ************************************************************(begin)
// **********************READ FIRST FILE***********************
// ************************************************************
while (fread(&runInfo, sizeof(RunInfo), 1, input1)) {
runID++;
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
if (runInfo.projectionIndex == P_interrupt) {
runID--;
break;
}
int nbParticle = runInfo.nbParticle;
std::vector<ParticleInfo> gammaAtCreation(nbParticle);
fread(&gammaAtCreation[0], sizeof(ParticleInfo), nbParticle, input1);
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
// printf("-1--runId %d, ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, nbParticle =
// %d\n",runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, nbParticle);
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
// angleOfDetector+totalAngleSpan/nbProjection*runInfo.projectionIndex means the angle between
// source direction and detector, which should be constant when source is rotating
double ra =
DegreeToRadian(angleOfDetector + totalAngleSpan / nbProjection * runInfo.projectionIndex);
centerOfDetector.m_x = distanceObjectDetector * cos(ra);
centerOfDetector.m_y = distanceObjectDetector * sin(ra);
centerOfDetector.m_z = 0;
for (int i = 0; i < nbParticle; ++i) {
// gamma selection: energy should be lower than 4095*10eV = 49.45 keV
if (gammaAtCreation[i].energy_keV >= 40.95 || gammaAtCreation[i].energy_keV <= 0.9)
continue; // gamma selection
gammaMomentum.m_x = gammaAtCreation[i].mx;
gammaMomentum.m_y = gammaAtCreation[i].my;
gammaMomentum.m_z = gammaAtCreation[i].mz;
if (!IsDetected(centerOfDetector, gammaMomentum, theta))
continue;
else {
pixeEvent.energy_10eV = floor(100 * gammaAtCreation[i].energy_keV + 0.5);
pixeEvent.projectionIndex = runInfo.projectionIndex;
pixeEvent.sliceIndex = runInfo.sliceIndex;
pixeEvent.pixelIndex = runInfo.pixelIndex;
eventVec.push_back(pixeEvent);
// fwrite(&pixeEvent, 7, 1, temp);
// fwrite(&pixeEvent, 7, 1, out);
count1++;
}
}
}
printf("---------------Number of PixeEvent in the first file: %lld------------------------\n",
count1);
fclose(input1);
// fclose(temp);
// ************************************************************(end)
// **********************READ FIRST FILE***********************
// ************************************************************
PixeEvent pp;
PixeEvent p;
for (int i = 0; i < nbProjection; ++i) {
int size = eventVec.size();
for (int j = 0; j < size; ++j) {
p = eventVec[j];
pp.energy_10eV = p.energy_10eV;
pp.projectionIndex = p.projectionIndex + i;
pp.sliceIndex = p.sliceIndex; // index of slices should be reset, starting from 0
pp.pixelIndex = p.pixelIndex;
pp.pixelIndex = p.pixelIndex;
// printf("__ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, Energy_10eV=%d\n",
// pp.projectionIndex, pp.sliceIndex, pp.pixelIndex, pp.energy_10eV);
fwrite(&pp, 7, 1, out);
}
}
// fclose(temp);
fclose(out);
// Recheck the output file in case
FILE* input2 =
fopen("../RT7_GDP_1Projs_1Slice_128Pixels_2000000_4MeV/PixeEvent_std_AtCreation.DAT", "rb");
PixeEvent ppp;
int proj = -1;
while (fread(&ppp, 7, 1, input2)) {
if (ppp.projectionIndex != proj) {
printf("__ProjectionIndex=%d\n", ppp.projectionIndex);
proj = ppp.projectionIndex;
}
// printf("__ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, Energy_10eV=%d\n",
// ppp.projectionIndex, ppp.sliceIndex, ppp.pixelIndex, ppp.energy_10eV);
}
fclose(input2);
}
@@ -0,0 +1,270 @@
//***********************************************************************************************************
// Concatenate_BinToStd_GammaAtExit.C
// Root command file
// Type: root Concatenate_BinToStd_GammaAtExit.C
//
// It is used in case of one interruption
// Read 2 output files GammaAtExit_1.dat and GammaAtExit_2.dat that are generated by Geant4
// tomography simulation It reads gamma at exit information, and rewrite the events in a binary file
// PixeEvent_std_AtExit.DAT
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
// Define a structure to read and write each event in the required binary format
struct PixeEvent
{
uint16_t energy_10eV;
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
struct ParticleInfo
{
float energy_keV;
float mx;
float my;
float mz;
};
struct RunInfo
{
// uint_16t
uint8_t projectionIndex; // 1 byte
uint16_t sliceIndex; //
uint16_t pixelIndex;
uint32_t nbParticle; // 4 bytes int
};
struct Point
{
double m_x;
double m_y;
double m_z;
};
bool IsDetected(Point poi1, Point poi2, double theta)
{
double a = (poi1.m_x * poi2.m_x + poi1.m_y * poi2.m_y + poi1.m_z * poi2.m_z)
/ sqrt(poi1.m_x * poi1.m_x + poi1.m_y * poi1.m_y + poi1.m_z * poi1.m_z)
/ sqrt(poi2.m_x * poi2.m_x + poi2.m_y * poi2.m_y + poi2.m_z * poi2.m_z);
if (a > 1.0) a = 1;
if (a < -1.0) a = -1;
double r = acos(a);
if (r > theta)
return false;
else
return true;
}
void Concatenate_BinToStd_GammaAtExit()
{
//***********************************************************************
//**************************Detection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 10;
const int nbSlice = 1;
const int nbPixel = 20;
double totalAngleSpan = 180.; // in degree
double angleOfDetector =
135.; // angle of detector relative to the incident direction of the primary protons //
double distanceObjectDetector = 22.; // 22 mm
double radiusOfDetector = 5.; // 5 mm
// double theta = atan(radiusOfDetector/distanceObjectDetector); //half apex angle of the right
// circular cone in radian
double theta = 70 * TMath::DegToRad(); // in radian
int P_interrupt = 6; // Projection of interruption
//***********************************************************************
//**************************Detection parameters (end)*******************
//***********************************************************************
// assuming there is one interruption
FILE* input1 = fopen("../build/GammaAtExit_1.dat", "rb");
FILE* input2 = fopen("../build/GammaAtExit_2.dat", "rb");
FILE* out = fopen("../build/PixeEvent_std_AtExit.DAT", "wb");
if (input1 == NULL) {
printf("error for opening the input GammaAtExit_1.dat file\n");
return;
}
if (input2 == NULL) {
printf("error for opening the input GammaAtExit_2.dat file\n");
return;
}
RunInfo runInfo;
PixeEvent pixeEvent;
Point centerOfDetector;
Point gammaMomentum;
long long count1 = 0;
long long count2 = 0;
int runID = -1; // index of simulations, namely runID, starting from 0
// ************************************************************
// **********************READ FIRST FILE (begin)***************
// ************************************************************
while (fread(&runInfo, sizeof(RunInfo), 1, input1)) {
runID++;
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
if (runInfo.projectionIndex == P_interrupt) {
runID--;
break;
}
int nbParticle = runInfo.nbParticle;
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
printf("-1--runId %d, ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, nbParticle = %d\n",
runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, nbParticle);
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
if (!nbParticle) continue;
std::vector<ParticleInfo> gammaAtExit(nbParticle);
fread(&gammaAtExit[0], sizeof(ParticleInfo), nbParticle, input1);
// if(runInfo.sliceIndex!=1) continue;
// if(runInfo.sliceIndex!=31&&runInfo.sliceIndex!=32) continue;
// if(runInfo.sliceIndex!=31) continue;
// angleOfDetector+totalAngleSpan/nbProjection*runInfo.projectionIndex means the angle between
// source direction and detector, which should be constant when source is rotating
double ra = TMath::DegToRad()
* (angleOfDetector + totalAngleSpan / nbProjection * runInfo.projectionIndex);
centerOfDetector.m_x = distanceObjectDetector * cos(ra);
centerOfDetector.m_y = distanceObjectDetector * sin(ra);
centerOfDetector.m_z = 0;
for (int i = 0; i < nbParticle; ++i) {
// gamma selection: energy should be lower than 4095*10eV = 49.45 keV
if (gammaAtExit[i].energy_keV >= 40.95 || gammaAtExit[i].energy_keV <= 0.9)
continue; // gamma selection
gammaMomentum.m_x = gammaAtExit[i].mx;
gammaMomentum.m_y = gammaAtExit[i].my;
gammaMomentum.m_z = gammaAtExit[i].mz;
if (!IsDetected(centerOfDetector, gammaMomentum, theta))
continue;
else {
pixeEvent.energy_10eV = floor(100 * gammaAtExit[i].energy_keV + 0.5);
pixeEvent.projectionIndex = runInfo.projectionIndex;
pixeEvent.sliceIndex = runInfo.sliceIndex;
pixeEvent.pixelIndex = runInfo.pixelIndex;
fwrite(&pixeEvent, 7, 1, out);
count1++;
}
}
}
printf("---------------Number of PixeEvent in the first file: %lld------------------------\n",
count1);
fclose(input1);
// ************************************************************
// **********************READ FIRST FILE (end)*****************
// ************************************************************
// ************************************************************
// **********************READ SECOND FILE (begin)**************
// ************************************************************
while (fread(&runInfo, sizeof(RunInfo), 1, input2)) {
runID++;
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
int nbParticle = runInfo.nbParticle;
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
printf("-2--runId %d, ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, nbParticle = %d\n",
runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, nbParticle);
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
if (!nbParticle) continue;
std::vector<ParticleInfo> gammaAtExit(nbParticle);
fread(&gammaAtExit[0], sizeof(ParticleInfo), nbParticle, input2);
// if(runInfo.sliceIndex!=1) continue;
// if(runInfo.sliceIndex!=31&&runInfo.sliceIndex!=32) continue;
// if(runInfo.sliceIndex!=31) continue;
// angleOfDetector+totalAngleSpan/nbProjection*runInfo.projectionIndex means the angle between
// source direction and detector, which should be constant when source is rotating
double ra = TMath::DegToRad()
* (angleOfDetector + totalAngleSpan / nbProjection * runInfo.projectionIndex);
centerOfDetector.m_x = distanceObjectDetector * cos(ra);
centerOfDetector.m_y = distanceObjectDetector * sin(ra);
centerOfDetector.m_z = 0;
for (int i = 0; i < nbParticle; ++i) {
// gamma selection: energy should be lower than 4095*10eV = 49.45 keV
if (gammaAtExit[i].energy_keV >= 40.95 || gammaAtExit[i].energy_keV <= 0.9)
continue; // gamma selection
gammaMomentum.m_x = gammaAtExit[i].mx;
gammaMomentum.m_y = gammaAtExit[i].my;
gammaMomentum.m_z = gammaAtExit[i].mz;
if (!IsDetected(centerOfDetector, gammaMomentum, theta))
continue;
else {
pixeEvent.energy_10eV = floor(100 * gammaAtExit[i].energy_keV + 0.5);
pixeEvent.projectionIndex = runInfo.projectionIndex;
pixeEvent.sliceIndex = runInfo.sliceIndex;
pixeEvent.pixelIndex = runInfo.pixelIndex;
fwrite(&pixeEvent, 7, 1, out);
count2++;
}
}
}
printf("---------------Number of PixeEvent in in the second file: %lld------------------------\n",
count2);
// ************************************************************
// **********************READ SECOND FILE (end)****************
// ************************************************************
printf("---------------Number of PixeEvent in total: %lld------------------------\n",
count1 + count2);
fclose(input2);
fclose(out);
// Recheck the output file in case
// FILE* input2 = fopen("PixeEvent_std_AtExit.DAT","rb");
// PixeEvent p;
// while(fread(&p, 7, 1, input2))
// {
// printf("__ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, Energy_10eV=%d\n",
// p.projectionIndex, p.sliceIndex, p.pixelIndex, p.energy_10eV);
// }
// fclose(input2);
}
@@ -0,0 +1,232 @@
//***********************************************************************************************************
// Concatenate_BinToStd_GammaAtExit_fabricate.C
// Root command file
// Use it by typing in the command line of Root terminal: root
// Concatenate_BinToStd_GammaAtExit_fabricate.C
//
//
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
#define PI 3.14159265f
// Define a structure to read and write each event in the required binary format
struct PixeEvent
{
uint16_t energy_10eV;
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
struct ParticleInfo
{
float energy_keV;
float mx;
float my;
float mz;
};
struct RunInfo
{
// uint_16t
uint8_t projectionIndex; // 1 byte
uint16_t sliceIndex; //
uint16_t pixelIndex;
uint32_t nbParticle; // 4 bytes int
};
double DegreeToRadian(double degree)
{
return (PI * degree / 180.);
}
struct Point
{
double m_x;
double m_y;
double m_z;
};
bool IsDetected(Point poi1, Point poi2, double theta)
{
double a = (poi1.m_x * poi2.m_x + poi1.m_y * poi2.m_y + poi1.m_z * poi2.m_z)
/ sqrt(poi1.m_x * poi1.m_x + poi1.m_y * poi1.m_y + poi1.m_z * poi1.m_z)
/ sqrt(poi2.m_x * poi2.m_x + poi2.m_y * poi2.m_y + poi2.m_z * poi2.m_z);
if (a > 1.0) a = 1;
if (a < -1.0) a = -1;
double r = acos(a);
if (r > theta)
return false;
else
return true;
}
void Concatenate_BinToStd_GammaAtExit_fabricate()
{
//***********************************************************************
//**************************Detection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 100;
const int nbSlice = 1;
const int nbPixel = 128;
double totalAngleSpan = 180.; // in degree
double angleOfDetector =
135.; // angle of detector relative to the incident direction of the primary protons //
double distanceObjectDetector = 22.; // 22 mm
double radiusOfDetector = 5.; // 5 mm
// double theta = atan(radiusOfDetector/distanceObjectDetector); //half apex angle of the right
// circular cone in radian double theta = 14.726*TMath::DegToRad(); // in radian
double theta = 70 * TMath::DegToRad(); // in radian
// double theta = 70*TMath::DegToRad(); // in radian
// double theta = DegreeToRadian(70);
int P_interrupt = 1; // Projection of interruption
//***********************************************************************
//**************************Detection parameters (end)*******************
//***********************************************************************
// assuming there is one interruption
FILE* input1 = fopen("../RT7_GDP_1Projs_1Slice_128Pixels_2000000_4MeV/GammaAtExit.dat", "rb");
FILE* out =
fopen("../RT7_GDP_1Projs_1Slice_128Pixels_2000000_4MeV/PixeEvent_std_AtExit.DAT", "wb");
// FILE* temp;
// temp =fopen("temp.DAT","wb");
if (input1 == NULL) {
printf("error for opening the input GammaAtExit.dat file\n");
return;
}
RunInfo runInfo;
PixeEvent pixeEvent;
Point centerOfDetector;
Point gammaMomentum;
long long count1 = 0;
long long count2 = 0;
int runID = -1; // index of simulations, namely runID, starting from 0
std::vector<PixeEvent> eventVec;
// ************************************************************(begin)
// **********************READ FIRST FILE***********************
// ************************************************************
while (fread(&runInfo, sizeof(RunInfo), 1, input1)) {
runID++;
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
if (runInfo.projectionIndex == P_interrupt) {
runID--;
break;
}
int nbParticle = runInfo.nbParticle;
std::vector<ParticleInfo> gammaAtExit(nbParticle);
fread(&gammaAtExit[0], sizeof(ParticleInfo), nbParticle, input1);
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
printf("-1--runId %d, ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, nbParticle = %d\n",
runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, nbParticle);
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
// angleOfDetector+totalAngleSpan/nbProjection*runInfo.projectionIndex means the angle between
// source direction and detector, which should be constant when source is rotating
double ra =
DegreeToRadian(angleOfDetector + totalAngleSpan / nbProjection * runInfo.projectionIndex);
centerOfDetector.m_x = distanceObjectDetector * cos(ra);
centerOfDetector.m_y = distanceObjectDetector * sin(ra);
centerOfDetector.m_z = 0;
for (int i = 0; i < nbParticle; ++i) {
// gamma selection: energy should be lower than 4095*10eV = 49.45 keV
if (gammaAtExit[i].energy_keV >= 40.95 || gammaAtExit[i].energy_keV <= 0.9)
continue; // gamma selection
gammaMomentum.m_x = gammaAtExit[i].mx;
gammaMomentum.m_y = gammaAtExit[i].my;
gammaMomentum.m_z = gammaAtExit[i].mz;
if (!IsDetected(centerOfDetector, gammaMomentum, theta))
continue;
else {
pixeEvent.energy_10eV = floor(100 * gammaAtExit[i].energy_keV + 0.5);
pixeEvent.projectionIndex = runInfo.projectionIndex;
pixeEvent.sliceIndex = runInfo.sliceIndex;
pixeEvent.pixelIndex = runInfo.pixelIndex;
eventVec.push_back(pixeEvent);
count1++;
}
}
}
printf("---------------Number of PixeEvent in the first file: %lld------------------------\n",
count1);
fclose(input1);
// fclose(temp);
// ************************************************************(end)
// **********************READ FIRST FILE***********************
// ************************************************************
// ************************************************************(begin)
// **********************READ SECOND FILE**********************
// ************************************************************
// temp =fopen("temp.DAT","rb");
PixeEvent pp;
PixeEvent p;
for (int i = 0; i < nbProjection; ++i) {
int size = eventVec.size();
for (int j = 0; j < size; ++j) {
p = eventVec[j];
pp.energy_10eV = p.energy_10eV;
pp.projectionIndex = p.projectionIndex + i;
pp.sliceIndex = p.sliceIndex; // index of slices should be reset, starting from 0
pp.pixelIndex = p.pixelIndex;
// printf("__ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, Energy_10eV=%d\n",
// pp.projectionIndex, pp.sliceIndex, pp.pixelIndex, pp.energy_10eV);
fwrite(&pp, 7, 1, out);
}
}
// ************************************************************(end)
// **********************READ SECOND FILE**********************
// ************************************************************
// fclose(temp);
fclose(out);
// Recheck the output file in case
FILE* input2 =
fopen("../RT7_GDP_1Projs_1Slice_128Pixels_2000000_4MeV/PixeEvent_std_AtExit.DAT", "rb");
PixeEvent ppp;
int proj = -1;
while (fread(&ppp, 7, 1, input2)) {
if (ppp.projectionIndex != proj) {
printf("__ProjectionIndex=%d\n", ppp.projectionIndex);
proj = ppp.projectionIndex;
}
// if(proj<20) printf("__ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, Energy_10eV=%d\n",
// ppp.projectionIndex, ppp.sliceIndex, ppp.pixelIndex, ppp.energy_10eV);
}
fclose(input2);
}
@@ -0,0 +1,276 @@
//***********************************************************************************************************
// Concatenate_BinToStd_ProtonAtExit.C
// Root command file
// Type: root Concatenate_BinToStd_ProtonAtExit.C
//
// It is used in case of interruption
// Read 2 output files ProtonAtExit_1.dat and ProtonAtExit_2.dat that are generated by Geant4
// tomography simulation It reads protons at exit information, and rewrite the events in a binary
// file StimEvent_std.DAT
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
// Define a structure to read and write each event in the required binary format
struct StimEvent
{
uint16_t energy_keV; // different from Pixe Event, it is in keV
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
struct ParticleInfo
{
float energy_keV;
float mx;
float my;
float mz;
};
struct RunInfo
{
// uint_16t
uint8_t projectionIndex; // 1 byte
uint16_t sliceIndex; //
uint16_t pixelIndex;
uint32_t nbParticle; // 4 bytes int
};
struct Point
{
double m_x;
double m_y;
double m_z;
};
bool IsDetected(Point poi1, Point poi2, double theta)
{
double a = (poi1.m_x * poi2.m_x + poi1.m_y * poi2.m_y + poi1.m_z * poi2.m_z)
/ sqrt(poi1.m_x * poi1.m_x + poi1.m_y * poi1.m_y + poi1.m_z * poi1.m_z)
/ sqrt(poi2.m_x * poi2.m_x + poi2.m_y * poi2.m_y + poi2.m_z * poi2.m_z);
if (a > 1.0) a = 1;
if (a < -1.0) a = -1;
double r = acos(a);
if (r > theta)
return false;
else
return true;
}
void Recheck()
{
// Recheck the output file in case
FILE* input3 = fopen("../build/StimEvent_std_Detector0_Aperture10.2.DAT", "rb");
StimEvent p;
double eventId = -1;
while (fread(&p, 7, 1, input3)) {
if (p.projectionIndex == 8 && p.sliceIndex == 64 && p.pixelIndex == 10) {
eventId++;
printf("StimEvent_%.0f ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, Energy_keV=%d keV\n",
eventId, p.projectionIndex, p.sliceIndex, p.pixelIndex, p.energy_keV);
}
}
fclose(input3);
}
void Concatenate_BinToStd_ProtonAtExit()
{
// Recheck();
// return;
//***********************************************************************
//**************************Detection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 10;
const int nbSlice = 128;
const int nbPixel = 20;
double totalAngleSpan = 180.; // in degree
// angle of detector relative to the incident direction of the primary protons at first projection
// for proton, it is fixed to 0 degree, namely opposite to the source
double angleOfDetector = 0.;
double distanceObjectDetector = 22.; // 22 mm
double radiusOfDetector = 5.; // 5 mm
// double theta = atan(radiusOfDetector/distanceObjectDetector); //half apex angle of the right
// circular cone in radian
double theta = 10.2 * TMath::DegToRad(); // in radian
int P_interrupt = 2; // Projection of interruption
//***********************************************************************
//**************************Detection parameters (end)*******************
//***********************************************************************
// assuming there is one interruption
FILE* input1 = fopen("../build/ProtonAtExit_1.dat", "rb");
FILE* input2 = fopen("../build/ProtonAtExit_2.dat", "rb");
FILE* out = fopen("../build/StimEvent_std.DAT", "wb");
if (input1 == NULL) {
printf("error for opening the input ProtonAtExit_1.dat file\n");
return;
}
if (input2 == NULL) {
printf("error for opening the input ProtonAtExit_2.dat file\n");
return;
}
RunInfo runInfo;
StimEvent stimEvent;
Point centerOfDetector;
Point protonMomentum;
long long count1 = 0;
long long count2 = 0;
int runID = -1; // index of simulations, namely runID, starting from 0
// ************************************************************(begin)
// **********************READ FIRST FILE***********************
// ************************************************************
while (fread(&runInfo, sizeof(RunInfo), 1, input1)) {
runID++;
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
if (runInfo.projectionIndex == P_interrupt) {
runID--;
break;
}
int nbParticle = runInfo.nbParticle;
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
printf("-1--runId %d, ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, nbParticle = %d\n",
runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, nbParticle);
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
if (!nbParticle) continue;
std::vector<ParticleInfo> protonAtExit(nbParticle);
fread(&protonAtExit[0], sizeof(ParticleInfo), nbParticle, input1);
// if(runInfo.sliceIndex!=1) continue;
// if(runInfo.sliceIndex!=31&&runInfo.sliceIndex!=32) continue;
// if(runInfo.sliceIndex!=31) continue;
// angleOfDetector+totalAngleSpan/nbProjection*runInfo.projectionIndex means the angle between
// source direction and detector, which should be constant when source is rotating
double ra = TMath::DegToRad()
* (angleOfDetector + totalAngleSpan / nbProjection * runInfo.projectionIndex);
centerOfDetector.m_x = distanceObjectDetector * cos(ra);
centerOfDetector.m_y = distanceObjectDetector * sin(ra);
centerOfDetector.m_z = 0;
for (int i = 0; i < nbParticle; ++i) {
// proton selection: energy should be lower than 4095 keV
if (protonAtExit[i].energy_keV >= 4095) continue; // proton selection
protonMomentum.m_x = protonAtExit[i].mx;
protonMomentum.m_y = protonAtExit[i].my;
protonMomentum.m_z = protonAtExit[i].mz;
if (!IsDetected(centerOfDetector, protonMomentum, theta))
continue;
else {
stimEvent.energy_keV = floor(protonAtExit[i].energy_keV + 0.5);
stimEvent.projectionIndex = runInfo.projectionIndex;
stimEvent.sliceIndex = runInfo.sliceIndex;
stimEvent.pixelIndex = runInfo.pixelIndex;
fwrite(&stimEvent, 7, 1, out);
count1++;
}
}
}
printf("---------------Number of StimEvent in the first file: %lld------------------------\n",
count1);
fclose(input1);
// ************************************************************
// **********************READ FIRST FILE (end)*****************
// ************************************************************
// ************************************************************
// **********************READ SECOND FILE (begin)**************
// ************************************************************
while (fread(&runInfo, sizeof(RunInfo), 1, input2)) {
runID++;
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
int nbParticle = runInfo.nbParticle;
//***********************************************************************
//**************************Print information (begin)********************
//***********************************************************************
printf("-2--runId %d, ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, nbParticle = %d\n",
runID, runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, nbParticle);
//***********************************************************************
//**************************Print information (end)**********************
//***********************************************************************
if (!nbParticle) continue;
std::vector<ParticleInfo> protonAtExit(nbParticle);
fread(&protonAtExit[0], sizeof(ParticleInfo), nbParticle, input2);
// if(runInfo.sliceIndex!=1) continue;
// if(runInfo.sliceIndex!=31) continue;
// if(runInfo.sliceIndex!=31&&runInfo.sliceIndex!=32) continue;
// angleOfDetector+totalAngleSpan/nbProjection*runInfo.projectionIndex means the angle between
// source direction and detector, which should be constant when source is rotating
double ra = TMath::DegToRad()
* (angleOfDetector + totalAngleSpan / nbProjection * runInfo.projectionIndex);
centerOfDetector.m_x = distanceObjectDetector * cos(ra);
centerOfDetector.m_y = distanceObjectDetector * sin(ra);
centerOfDetector.m_z = 0;
for (int i = 0; i < nbParticle; ++i) {
// proton selection: energy should be lower than 4095 keV
if (protonAtExit[i].energy_keV >= 4095) continue; // proton selection
protonMomentum.m_x = protonAtExit[i].mx;
protonMomentum.m_y = protonAtExit[i].my;
protonMomentum.m_z = protonAtExit[i].mz;
if (!IsDetected(centerOfDetector, protonMomentum, theta))
continue;
else {
stimEvent.energy_keV = floor(protonAtExit[i].energy_keV + 0.5);
stimEvent.projectionIndex = runInfo.projectionIndex;
stimEvent.sliceIndex = runInfo.sliceIndex;
stimEvent.pixelIndex = runInfo.pixelIndex;
fwrite(&stimEvent, 7, 1, out);
count2++;
}
}
}
printf("---------------Number of StimEvent in in the second file: %lld------------------------\n",
count2);
// ************************************************************
// **********************READ SECOND FILE (end)****************
// ************************************************************
printf("---------------Number of StimEvent in total: %lld------------------------\n",
count1 + count2);
fclose(input2);
fclose(out);
}
@@ -0,0 +1,70 @@
//***********************************************************************************************************
// Extract_Slice.C
// Root command file
// Use it by typing in the command line of Root terminal: root Extract_Slice.C
//
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
#define PI 3.14159265f
// Define a structure to read and write each event in the required binary format
struct PixeEvent
{
uint16_t energy_10eV;
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
// to extract a certain slice or slices
void Extract_Projection()
{
// FILE *in =fopen("PixeEvent_std_AtCreation.DAT","rb");
FILE* in = fopen("../build/PixeEvent_std_AtExit_Detector135_Aperture70.DAT", "rb");
// FILE* out = fopen("PixeEvent_std_AtCreation_50Projections.DAT","wb");
FILE* out = fopen("../build/PixeEvent_std_AtExit_Detector135_Aperture70_50Projections.DAT", "wb");
if (in == NULL) {
printf("error for opening the intput file\n");
return;
}
PixeEvent p;
PixeEvent pp;
vector<int> valid_projections;
for (int i = 0; i < 50; ++i) {
int p = 2 * i;
valid_projections.push_back(p);
}
while (fread(&p, 7, 1, in)) {
int key = p.projectionIndex;
if (std::find(valid_projections.begin(), valid_projections.end(), key)
!= valid_projections.end()) {
pp.energy_10eV = p.energy_10eV;
pp.projectionIndex = p.projectionIndex / 2;
pp.sliceIndex = p.sliceIndex; // index of slices should be reset, starting from 0
pp.pixelIndex = p.pixelIndex;
pp.pixelIndex = p.pixelIndex;
// printf("__ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, Energy_10eV=%d\n",
// pp.projectionIndex, pp.sliceIndex, pp.pixelIndex, pp.energy_10eV);
fwrite(&pp, 7, 1, out);
}
}
fclose(in);
fclose(out);
}
@@ -0,0 +1,66 @@
//***********************************************************************************************************
// Extract_Slice.C
// Root command file
// Use it by typing in the command line of Root terminal: root Extract_Slice.C
//
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
#define PI 3.14159265f
// Define a structure to read and write each event in the required binary format
struct PixeEvent
{
uint16_t energy_10eV;
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
// to extract a certain slice or slices
void Extract_Slice()
{
int start_slice = 0; // start_slice: the first slice you would like to select
int end_slice = 0; // end_slice: the last slice you would like to select
FILE* in = fopen("../build/PixeEvent_std_AtCreation.DAT", "rb");
// FILE *in =fopen("PixeEvent_std_AtExit.DAT.DAT","rb");
FILE* out = fopen("../build/PixeEvent_std_AtCreation_slice.DAT", "wb");
// FILE* out = fopen("PixeEvent_std_AtExit_slice.DAT","wb");
if (in == NULL) {
printf("error for opening the intput file\n");
return;
}
PixeEvent p;
PixeEvent pp;
while (fread(&p, 7, 1, in)) {
if (p.sliceIndex >= start_slice && p.sliceIndex <= end_slice) {
pp.energy_10eV = p.energy_10eV;
pp.projectionIndex = p.projectionIndex;
pp.sliceIndex =
p.sliceIndex - start_slice; // index of slices should be reset, starting from 0
pp.pixelIndex = p.pixelIndex;
pp.pixelIndex = p.pixelIndex;
// printf("__ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, Energy_10eV=%d\n",
// pp.projectionIndex, pp.sliceIndex, pp.pixelIndex, pp.energy_10eV);
fwrite(&pp, 7, 1, out);
}
}
fclose(in);
fclose(out);
}
@@ -0,0 +1,93 @@
//***********************************************************************************************************
// LocateInterruption_GammaAtExit.C
// Root command file
// Type: root LocateInterruption_GammaAtExit.C
//
// It is used by reading GammaAtExit.dat file to locate at which projection the interruption happens
//
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
struct ParticleInfo
{
float energy_keV;
float mx;
float my;
float mz;
};
// struct ParticleInfo
// {
// float energy_keV;
// float mx;
// float my;
// float mz;
// float x;
// float y;
// float z;
// };
struct RunInfo
{
// uint_16t
uint8_t projectionIndex; // 1 byte
uint16_t sliceIndex; //
uint16_t pixelIndex;
uint32_t nbParticle; // 4 bytes int
};
void LocateInterruption_GammaAtExit()
{
FILE* input = fopen("../build/GammaAtExit_1.dat", "rb");
if (input == NULL) {
printf("error for opening the input file\n");
return;
}
RunInfo runInfo;
int projection = 0; // the projection when interruption occurs
//***********************************************************************
//**************************Detection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 10;
const int nbSlice = 1;
const int nbPixel = 20;
//***********************************************************************
//**************************Detection parameters (end)*******************
//***********************************************************************
int runID = -1;
while (fread(&runInfo, sizeof(RunInfo), 1, input)) {
runID++;
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
int nbParticle = runInfo.nbParticle;
std::vector<ParticleInfo> gammaAtExit(nbParticle);
fread(&gammaAtExit[0], sizeof(ParticleInfo), nbParticle, input);
printf("---------ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, nbParticle = %d\n",
runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, nbParticle);
projection = runInfo.projectionIndex;
}
printf("-----------------------It is interrupted at ProjectionIndex = %d--------------------\n",
projection);
fclose(input);
}
@@ -0,0 +1,93 @@
//***********************************************************************************************************
// LocateInterruption_ProtonAtExit.C
// Root command file
// Type: root LocateInterruption_ProtonAtExit.C
//
// It is used by reading ProtonAtExit.dat file to locate at which projection the interruption is
//
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
struct ParticleInfo
{
float energy_keV;
float mx;
float my;
float mz;
};
// struct ParticleInfo
// {
// float energy_keV;
// float mx;
// float my;
// float mz;
// float x;
// float y;
// float z;
// };
struct RunInfo
{
// uint_16t
uint8_t projectionIndex; // 1 byte
uint16_t sliceIndex; //
uint16_t pixelIndex;
uint32_t nbParticle; // 4 bytes int
};
void LocateInterruption_ProtonAtExit()
{
FILE* input = fopen("../build/ProtonAtExit_1.dat", "rb");
if (input == NULL) {
printf("error for opening the input file\n");
return;
}
RunInfo runInfo;
int projection = 0; // the projection when interruption occurs
//***********************************************************************
//**************************Detection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 10;
const int nbSlice = 128;
const int nbPixel = 20;
//***********************************************************************
//**************************Detection parameters (end)*******************
//***********************************************************************
int runID = -1;
while (fread(&runInfo, sizeof(RunInfo), 1, input)) {
runID++;
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
int nbParticle = runInfo.nbParticle;
std::vector<ParticleInfo> protonAtExit(nbParticle);
fread(&protonAtExit[0], sizeof(ParticleInfo), nbParticle, input);
printf("---------ProjectionIndex=%d, SliceIndex=%d, PixelIndex=%d, nbParticle = %d\n",
runInfo.projectionIndex, runInfo.sliceIndex, runInfo.pixelIndex, nbParticle);
projection = runInfo.projectionIndex;
}
printf("-----------------------It is interrupted at ProjectionIndex = %d--------------------\n",
projection);
fclose(input);
}
@@ -0,0 +1,143 @@
//***********************************************************************************************************
// Spectrum_gamma.C
// Root command file
// Type: root Spectrum_gamma.C
//
// It visualizes the spectrum of X-rays and plots a histogram by reading
// simulation result GammaAtCreation.dat or GammaAtExit.dat
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
// Define a structure to read and write each event in the required binary format
struct RunInfo
{
// uint_16t
uint8_t projectionIndex; // 1 byte
uint16_t sliceIndex; //
uint16_t pixelIndex;
uint32_t nbParticle; // 4 bytes int
};
struct ParticleInfo
{
float energy_keV;
float mx;
float my;
float mz;
};
// struct ParticleInfo
//{
// float energy_keV;
// float mx;
// float my;
// float mz;
// float x;
// float y;
// float z;
//};
void Plot(vector<double>& energies, int bin, double eMin, double eMax)
{
auto mycanvas = new TCanvas("canvas", "canvas", 800, 50, 600, 600);
gPad->SetLeftMargin(0.15);
// unit is in keV
auto hist = new TH1D("hist (keV)", "Spectrum of photons", bin, eMin, eMax);
for (int i = 0; i < energies.size(); ++i) {
hist->Fill(energies[i]);
}
hist->Draw();
hist->GetXaxis()->SetTitle("Energy (keV)");
hist->GetYaxis()->SetTitle("Counts");
hist->GetXaxis()->CenterTitle();
hist->GetYaxis()->CenterTitle();
mycanvas->Print("spectrum_gamma.png");
}
void Spectrum_gamma()
{
FILE* input = fopen("../build/GammaAtExit.dat", "rb");
if (input == NULL) {
printf("error for opening the input file\n");
return;
}
//***********************************************************************
//**************************Selection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 10;
const int nbSlice = 1;
const int nbPixel = 20;
int projection_index_begin = 0; // starter of the projection selected
int projection_index_end = 0; // end of the projection selected
int slice_index_begin = 0; // starter of the slice selected
int slice_index_end = 0; // end of the slice selected
//********************Parameters for spectrum***************************
int bin = 100;
double eMin = 0; // keV
double eMax = 0; // keV
//***********************************************************************
//**************************Selection parameters (end)*******************
//***********************************************************************
RunInfo runInfo;
vector<double> energies;
int runID = -1; // index of simulations, namely runID, starting from 0
// while(!feof(input)) //if not the end, read
while (fread(&runInfo, sizeof(RunInfo), 1, input)) {
runID++;
int nbParticle = runInfo.nbParticle;
// ***********the following codes are used
// if**************************************(begin)
// ***********the index of projection, slice and pixel is not correctly
// configured in the simulation
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
//************************************************************************(end)
if (!nbParticle) continue;
std::vector<ParticleInfo> particles(nbParticle);
fread(&particles[0], sizeof(ParticleInfo), nbParticle, input);
if (runInfo.projectionIndex >= projection_index_begin
&& runInfo.projectionIndex <= projection_index_end)
{
if (runInfo.sliceIndex >= slice_index_begin && runInfo.sliceIndex <= slice_index_end) {
for (int i = 0; i < nbParticle; ++i) {
// printf("--%d, %.9e\n", i, particles[i].energy_keV);
energies.push_back(particles[i].energy_keV);
if (particles[i].energy_keV > eMax) eMax = particles[i].energy_keV;
}
}
}
else
break;
}
fclose(input);
Plot(energies, bin, eMin, eMax + 10);
}
@@ -0,0 +1,129 @@
//***********************************************************************************************************
// Spectrum_proton.C
// Root command file
// Type: root Spectrum_proton.C
//
// It visualizes the spectrum of protons and plots a histogram by reading
// simulation result ProtonAtExit.dat
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
// Define a structure to read and write each event in the required binary format
struct RunInfo
{
// uint_16t
uint8_t projectionIndex; // 1 byte
uint16_t sliceIndex; //
uint16_t pixelIndex;
uint32_t nbParticle; // 4 bytes int
};
struct ParticleInfo
{
float energy_keV;
float mx;
float my;
float mz;
};
void Plot(vector<double>& energies, int bin, double eMin, double eMax)
{
auto mycanvas = new TCanvas("canvas", "canvas", 800, 50, 600, 600);
gPad->SetLeftMargin(0.15);
// unit is in keV
auto hist = new TH1D("hist (keV)", "Spectrum of protons", bin, eMin, eMax);
for (int i = 0; i < energies.size(); ++i) {
hist->Fill(energies[i]);
}
hist->Draw();
hist->GetXaxis()->SetTitle("Energy (keV)");
hist->GetYaxis()->SetTitle("Counts");
hist->GetXaxis()->CenterTitle();
hist->GetYaxis()->CenterTitle();
mycanvas->Print("spectrum_proton.png");
}
void Spectrum_proton()
{
FILE* input = fopen("../build/ProtonAtExit.dat", "rb");
if (input == NULL) {
printf("error for opening the input file\n");
return;
}
//***********************************************************************
//**************************Selection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 10;
const int nbSlice = 128;
const int nbPixel = 20;
int projection_index_begin = 0; // starter of the projection selected
int projection_index_end = 0; // end of the projection selected
int slice_index_begin = 64; // starter of the slice selected
int slice_index_end = 64; // end of the slice selected
//********************Parameters for spectrum***************************
int bin = 100;
double eMin = 0; // keV
double eMax = 0; // keV
//***********************************************************************
//**************************Selection parameters (end)*******************
//***********************************************************************
RunInfo runInfo;
vector<double> energies;
int runID = -1; // index of simulations, namely runID, starting from 0
// while(!feof(input)) //if not the end, read
while (fread(&runInfo, sizeof(RunInfo), 1, input)) {
runID++;
int nbParticle = runInfo.nbParticle;
// ***********the following codes are used
// if**************************************(begin)
// ***********the index of projection, slice and pixel is not correctly
// configured in the simulation
runInfo.projectionIndex = runID / (nbSlice * nbPixel);
int remain = runID % (nbSlice * nbPixel);
runInfo.sliceIndex = remain / nbPixel;
runInfo.pixelIndex = remain % nbPixel;
//******************************************************************************************(end)
if (!nbParticle) continue;
std::vector<ParticleInfo> proton(nbParticle);
fread(&proton[0], sizeof(ParticleInfo), nbParticle, input);
if (runInfo.projectionIndex >= projection_index_begin
&& runInfo.projectionIndex <= projection_index_end)
{
if (runInfo.sliceIndex >= slice_index_begin && runInfo.sliceIndex <= slice_index_end) {
for (int i = 0; i < nbParticle; ++i) {
energies.push_back(proton[i].energy_keV);
if (proton[i].energy_keV > eMax) eMax = proton[i].energy_keV;
}
}
}
else
break;
}
fclose(input);
Plot(energies, bin, eMin, eMax + 10);
}
@@ -0,0 +1,103 @@
//***********************************************************************************************************
// TomoSpectrum.C
// Root command file
// Type: root TomoSpectrum.C
//
// It visualizes the spectrum of X-rays and plots a graph by reading PixeEvent data.
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
struct PixeEvent
{
uint16_t energy_10eV;
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
void Plot(int nbChannels, vector<int>& X, vector<int>& Y)
{
gROOT->Reset();
auto mycanvas = new TCanvas("canvas", "canvas", 800, 50, 600, 600);
mycanvas->ToggleEventStatus();
gPad->SetLeftMargin(0.15);
auto graph = new TGraph(nbChannels, X.data(), Y.data());
graph->SetLineColor(8);
graph->Draw("AL");
graph->SetLineColor(8);
graph->SetTitle("TOMO Energy Spectrum");
graph->GetXaxis()->SetTitle("ADC channels");
graph->GetYaxis()->SetTitle("Nb events");
graph->GetXaxis()->CenterTitle();
graph->GetYaxis()->CenterTitle();
mycanvas->Print("TomoSpectrum.png");
}
void TomoSpectrum()
{
FILE* input = fopen("../build/PixeEvent_std_AtExit_Detector135_Aperture70.DAT", "rb");
if (input == NULL) {
printf("----------error for opening the input file--------------\n");
return;
}
//***********************************************************************
//**************************Selection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 10;
const int nbSlice = 1;
const int nbPixel = 20;
int projection_index_begin = 0; // starter of the projection selected
int projection_index_end = 0; // end of the projection selected
int slice_index_begin = 0; // starter of the slice selected
int slice_index_end = 0; // end of the slice selected
//***********************************************************************
//**************************Selection parameters (end)*******************
//***********************************************************************
int nbChannels = 4096;
vector<int> X(nbChannels); // save channels 1-4096, index X: 0-4095
vector<int> Y(nbChannels); // save event counts for channel 1-4096, index Y: 0-4095
PixeEvent p;
while (fread(&p, 7, 1, input)) {
if (p.projectionIndex >= projection_index_begin && p.projectionIndex <= projection_index_end) {
if (p.sliceIndex >= slice_index_begin && p.sliceIndex <= slice_index_end) {
// printf("%d %d %d\n",p.projectionIndex, p.sliceIndex, p.energy_10eV);
Y[p.energy_10eV - 1] = Y[p.energy_10eV - 1] + 1;
}
}
}
fclose(input);
for (int i = 0; i < nbChannels; ++i) {
X[i] = 1 + i;
}
FILE* out = fopen("Spectrum.txt", "wb");
for (int i = 0; i < nbChannels; ++i) {
fprintf(out, "%d\t%d\n", X[i], Y[i]);
}
fclose(out);
Plot(nbChannels, X, Y);
}
@@ -0,0 +1,120 @@
//***********************************************************************************************************
// TomoSpectrum_HIST.C
// Root command file
// Type: root TomoSpectrum_HIST.C
//
// It visualizes the spectrum of X-rays and plots a histogram by reading PixeEvent data
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
struct PixeEvent
{
uint16_t energy_10eV;
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
void Plot(vector<double>& energies, int bin, double eMin, double eMax)
{
gROOT->Reset();
auto mycanvas = new TCanvas("canvas", "canvas", 800, 50, 600, 600);
mycanvas->ToggleEventStatus();
gPad->SetLeftMargin(0.15);
auto hist = new TH1D("HIST", "Spectrum", bin, eMin, eMax);
for (int i = 0; i < energies.size(); ++i) {
hist->Fill(energies[i]);
}
hist->Draw();
hist->SetTitle("TOMO Energy Spectrum");
hist->GetXaxis()->SetTitle("ADC channels");
hist->GetYaxis()->SetTitle("Nb events");
hist->GetXaxis()->CenterTitle();
hist->GetYaxis()->CenterTitle();
// hist->GetYaxis()->SetTitleOffset(2);
mycanvas->Print("TomoSpectrum_hist.png");
}
void TomoSpectrum_HIST()
{
FILE* input = fopen("../build/PixeEvent_std_AtExit_Detector135_Aperture70.DAT", "rb");
if (input == NULL) {
printf("----------error for opening the input file--------------\n");
return;
}
//***********************************************************************
//**************************Selection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 10;
const int nbSlice = 1;
const int nbPixel = 20;
int projection_index_begin = 0; // starter of the projection selected
int projection_index_end = 0; // end of the projection selected
int slice_index_begin = 0; // starter of the slice selected
int slice_index_end = 0; // end of the slice selected
//********************Parameters for spectrum***************************
int nbChannels = 4096;
double eMin = 0; // initialization
double eMax = 0; //
//***********************************************************************
//**************************Selection parameters (end)*******************
//***********************************************************************
vector<double> energies;
PixeEvent p;
while (fread(&p, 7, 1, input)) {
if (p.projectionIndex >= projection_index_begin && p.projectionIndex <= projection_index_end) {
if (p.sliceIndex >= slice_index_begin && p.sliceIndex <= slice_index_end) {
energies.push_back(p.energy_10eV);
if (p.energy_10eV > eMax) eMax = p.energy_10eV;
}
}
}
fclose(input);
long int size = energies.size();
vector<int> X(nbChannels); // save channels 1-4096
vector<int> Y(nbChannels);
for (long int i = 0; i < size; ++i) {
int energy = energies[i];
Y[energy - 1] = Y[energy - 1] + 1;
}
for (int i = 0; i < nbChannels; ++i) {
X[i] = 1 + i;
}
FILE* out = fopen("Spectrum_hist.txt", "wb");
for (int i = 0; i < nbChannels; ++i) {
fprintf(out, "%d\t%d\n", X[i], Y[i]);
}
fclose(out);
Plot(energies, nbChannels, 0, nbChannels);
}
@@ -0,0 +1,122 @@
//***********************************************************************************************************
// TomoSpectrum_HIST_proton.C
// Root command file
// Type: root TomoSpectrum_HIST_proton.C
//
// It visualizes the spectrum of protons and plots a histogram by reading StimEvent data
//
// More information is available in UserGuide
// Created by Z.LI LP2i Bordeaux 2022
//***********************************************************************************************************
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// using namespace std;
struct StimEvent
{
uint16_t energy_keV; // different from Pixe Event, it is in keV
uint16_t pixelIndex;
uint16_t sliceIndex;
uint8_t projectionIndex;
};
void Plot(vector<double>& energies, int bin, double eMin, double eMax)
{
gROOT->Reset();
auto mycanvas = new TCanvas("canvas", "canvas", 800, 50, 600, 600);
mycanvas->ToggleEventStatus();
gPad->SetLeftMargin(0.15);
auto hist = new TH1D("HIST", "Spectrum", bin, eMin, eMax);
for (int i = 0; i < energies.size(); ++i) {
hist->Fill(energies[i]);
}
hist->Draw();
hist->SetTitle("TOMO Energy Spectrum");
hist->GetXaxis()->SetTitle("ADC channels");
hist->GetYaxis()->SetTitle("Nb events");
hist->GetXaxis()->CenterTitle();
hist->GetYaxis()->CenterTitle();
// hist->GetYaxis()->SetTitleOffset(2);
mycanvas->Print("TomoSpectrum_hist_proton.png");
}
void TomoSpectrum_HIST_proton()
{
FILE* input = fopen("../build/StimEvent_std_Detector0_Aperture10.2.DAT", "rb");
if (input == NULL) {
printf("----------error for opening the input file--------------\n");
return;
}
//***********************************************************************
//**************************Selection parameters (begin)*****************
//***********************************************************************
const int nbProjection = 10;
const int nbSlice = 128;
const int nbPixel = 20;
int projection_index_begin = 0; // starter of the projection selected
int projection_index_end = 0; // end of the projection selected
int slice_index_begin = 64; // starter of the slice selected
int slice_index_end = 64; // end of the slice selected
//********************Parameters for spectrum***************************
int nbChannels = 4096;
double eMin = 0; // initialization
double eMax = 0; //
//***********************************************************************
//**************************Selection parameters (end)*******************
//***********************************************************************
vector<double> energies;
StimEvent s;
while (fread(&s, 7, 1, input)) {
if (s.projectionIndex >= projection_index_begin && s.projectionIndex <= projection_index_end) {
if (s.sliceIndex >= slice_index_begin && s.sliceIndex <= slice_index_end) {
energies.push_back(s.energy_keV);
if (s.energy_keV > eMax) eMax = s.energy_keV;
}
}
}
fclose(input);
if (eMax > 4096) printf("---error in data----\n");
long int size = energies.size();
vector<int> X(nbChannels); // save channels 1-4096
vector<int> Y(nbChannels);
for (long int i = 0; i < size; ++i) {
int energy = energies[i];
Y[energy - 1] = Y[energy - 1] + 1;
}
for (int i = 0; i < nbChannels; ++i) {
X[i] = 1 + i;
}
FILE* out = fopen("Spectrum_hist_proton.txt", "wb");
for (int i = 0; i < nbChannels; ++i) {
fprintf(out, "%d\t%d\n", X[i], Y[i]);
}
fclose(out);
Plot(energies, nbChannels, 0, nbChannels);
}
@@ -0,0 +1,180 @@
import sys
import struct
import math
import numpy as np
# lists for super resolution (vol_work) and regular resolution (vol_result)
vol_work = []
vol_result = []
############################################################################
# size image 128x128 -> 500 microm -> resol x,y : 3.90625 microm #
# nb slices 128 -> 500 microm -> resol z : 3.90625 microm #
############################################################################
sizex = 128
sizey = 128
sizez = 128
resolx = 3.90625
resoly = 3.90625
resolz = 3.90625
superres = 8 # factor of super resolution
# sphere 1 (radius) - outer sphere
r1 = 196
# sphere 2 (radius) - inner sphere
r2 = 171
# density values for sphere 1 and sphere 2
type = 2 # type for constructing a STIM or PIXE phantom
# type = 1, STIM phantom, density value for STIM in 0.01 g/cm3
# type =2, PIXE phantom, density value for PIXE in 0.000001 g/cm3, namely microgram/cm3
value1 = 0
value2 = 0
if type == 1:
value1 = 108
value2 = 0
elif type == 2:
value1 = 54000
value2 = 0
# center of two spheres
x0 = 0.0
y0 = 0.0
z0 = -1.953125
# size in super resolution by voxel
super_sizex = sizex * superres
super_sizey = sizey * superres
super_sizez = sizez * superres
center_shift = sizex / 2 # translation of half scan
def make_sphere_center(r, x, y, z, value):
rsample = (r / resolx) * superres # radius in super resolution by voxel
xsample = (x / resolx) * superres
ysample = (y / resoly) * superres
zsample = (z / resolz) * superres
center_shift_sample = center_shift * superres # translation of the center for x (i) and y (j) axis
print(rsample, xsample, ysample, zsample)
number = 0
for k in range(0, super_sizez):
for j in range(0, super_sizey):
for i in range(0, super_sizex):
ii = i + 0.5
jj = j + 0.5
kk = k + 0.5
res = pow((ii - xsample - center_shift_sample), 2) / (rsample * rsample) + \
pow((jj - ysample - center_shift_sample), 2) / (rsample * rsample) + \
pow((kk - zsample - center_shift_sample), 2) / (rsample * rsample) # z-axis correction done
# if the point (ii, jj, kk) is in the sphere, we attribute the voxel (i,j, k) value
if (res <= 1.0):
vol_work[i + j * super_sizex + k * super_sizex * super_sizey] = value
number += 1
print(number)
# initialisation for two tables vol_result (128*128*128), vol_work (128*superres)*(128*superres)*(128*superres)
def initialize():
for k in range(0, sizez):
for j in range(0, sizey):
for i in range(0, sizex):
vol_result.append(0.0)
for k in range(0, super_sizez):
for j in range(0, super_sizey):
for i in range(0, super_sizex):
vol_work.append(0.0)
# Calculate the vol_result based on vol_work
def undersample():
x = 0
y = 0
z = 0
for k in range(0, super_sizez, superres):
for j in range(0, super_sizey, superres):
for i in range(0, super_sizex, superres):
# print ("***",i,j,k)
total = 0
for kk in range(0, superres):
for jj in range(0, superres):
for ii in range(0, superres):
total = total + vol_work[
i + ii + (j + jj) * super_sizex + (k + kk) * (super_sizex * super_sizey)]
vol_result[x + y * sizex + z * (sizex * sizey)] = total / (superres * superres * superres)
# print ("###",vol_result[x+y*sizex+z*(sizex*sizey)])
x += 1
y += 1
x = 0
z += 1
y = 0
# save the total volume of super resolution
def save_whole_work(file):
fd = open(file, "wb")
for i in range(0, len(vol_work)):
fd.write(struct.pack("f", vol_work[i]))
fd.close()
# save one slice in super resolution vol_work
# 0<=slice<super_sizez (128*8=1024)
def save_workslice(file, slice):
fd = open(file, "wb")
for j in range(0, super_sizey):
for i in range(0, super_sizex):
fd.write(struct.pack("f", vol_work[i + j * super_sizex + slice * super_sizex * super_sizey]))
fd.close()
# save the total result volume
def save_whole_result(file):
fd = open(file, "wb")
for i in range(0, len(vol_result)):
fd.write(struct.pack("f", vol_result[i]))
fd.close()
# save one slie in regular resolution vol_result
# 0<=slice<128
def save_slice(file, slice):
fd = open(file, "wb")
for j in range(0, sizey):
for i in range(0, sizex):
fd.write(struct.pack("f", vol_result[i + j * sizex + slice * sizex * sizey]))
fd.close()
print("------intialisation------")
initialize()
print("------end intialisation------")
print("------begin sphere 1------")
make_sphere_center(r1, x0, y0, z0, value1)
print("------end sphere 1------")
print("------begin sphere 2------")
make_sphere_center(r2, x0, y0, z0, value2)
print("------end sphere 2------")
print("------begin undersample------")
undersample()
print("------end undersample------")
print("The length of vol_work: ", len(vol_work))
print("The length of vol_result: ", len(vol_result))
# print ("------begin save slice 63 ------")
# save_slice("./slice_63.dat",63)
# print ("------end save slice 63 ------")
save_whole_result("./vol_result.dat")
save_whole_work("./vol_work.dat")
print("------end save work------")
@@ -0,0 +1,265 @@
import sys
import struct
import math
# tables for super resolution (vol_work) and regular resolution (vol_result)
vol_work = []
vol_result = []
############################################################################
# size image 128x128 -> 76.464 microm -> resol x,y : 0,597375 microm #
# nb slices 128 -> 201,217 microm -> resol z : 1,57200781 microm #
# slice of interest : 11 -> 18,07 microm #
############################################################################
sizex = 128
sizey = 128
sizez = 128
double_sizez = 256 # for computation only
resolx = 0.597375
resoly = 0.597375
resolz = 1.57200781
superres = 8
slice = 11
# ellipsoide 1 (semi-axes, center, rotation z, value) - skin
a1 = 20.61
b1 = 21.42
c1 = 187.82
x1 = 0.0
y1 = 0.0
z1 = 0.0
rz1 = 0.0
value1 = 49.73
# ellipsoide 2 (semi-axes, center, rotation z, value) - body
a2 = 18.61
b2 = 19.01
c2 = 186.64
x2 = -0.39
y2 = 0.0
z2 = 0.0
rz2 = 0.0
value2 = 40.85
# ellipsoide 3 (semi-axes, center, rotation z, value) - core 1
a3 = 1.95
b3 = 3.23
c3 = 4.32
x3 = 1.97
y3 = -7.09
z3 = 18.07
rz3 = 0.0
value3 = 66.26
# ellipsoide 4 (semi-axes, center, rotation z, value) - core 2
a4 = 2.08
b4 = 2.46
c4 = 4.32
x4 = 8.27
y4 = -3.15
z4 = 18.07
rz4 = 0.0
value4 = 60.23
# ellipsoide 5 (semi-axes, center, rotation z, value) - intestine
a5 = 3.67
b5 = 16.48
c5 = 28.68
x5 = 1.25
y5 = 0.61
z5 = 0
rz5 = -58.99
value5 = 54.06
# ellipsoide 6 ((emi-axes, center, rotation z, value) - region titane
a6 = 1.62
b6 = 1.95
c6 = 1.62
x6 = 6.25
y6 = 3.61
z6 = 18.07
rz6 = 0.0
value6 = 75.14
# size in super resolution by voxel
super_sizex = sizex * superres
super_sizey = sizey * superres
super_sizez = double_sizez * superres # we will save only half of the z
center_shift = sizex / 2 # for x and y axis
center_shift_z = double_sizez / 2
def make_ellipse_center(a, b, c, x, y, z, rz, value):
asample = (a / resolx) * superres
bsample = (b / resoly) * superres
csample = (c / resolz) * superres
# if (rz != 0.0):
rzsample = math.radians(rz) # angle in radians
xsample = (x / resolx) * superres
ysample = (y / resoly) * superres
zsample = (z / resolz) * superres
center_shift_sample = center_shift * superres # translation of center for x and y axis
center_shift_z_sample = center_shift_z * superres # translation of center for z axis
print(asample, bsample, csample, xsample, ysample, zsample)
number = 0 ## debug
# a loop in axes of voxels
for k in range(0, super_sizez):
for j in range(0, super_sizey):
for i in range(0, super_sizex):
ii = i + 0.5
jj = j + 0.5
kk = k + 0.5
res = pow(((ii - xsample - center_shift_sample) * math.cos(rzsample) + (
jj - ysample - center_shift_sample) * math.sin(rzsample)), 2) / (asample * asample) + \
pow(((ii - xsample - center_shift_sample) * math.sin(rzsample) - (
jj - ysample - center_shift_sample) * math.cos(rzsample)), 2) / (bsample * bsample) + \
((kk - zsample - center_shift_z_sample) * (kk - zsample - center_shift_z_sample)) / (
csample * csample) # z-axis correction done
# print(res)
# if the voxel belongs to the ellipsoide, set the value
if (res <= 1.0):
vol_work[i + j * super_sizex + k * super_sizex * super_sizey] = value
number += 1
print(number)
# initialisation
def initialize():
for k in range(0, double_sizez):
for j in range(0, sizey):
for i in range(0, sizex):
vol_result.append(0.0)
for k in range(0, super_sizez):
for j in range(0, super_sizey):
for i in range(0, super_sizex):
vol_work.append(0.0)
# Calculate the vol_result based on vol_work
def undersample():
x = 0
y = 0
z = 0
for k in range(0, super_sizez, superres):
for j in range(0, super_sizey, superres):
for i in range(0, super_sizex, superres):
# on se place sur v1 et on recupere les valeurs de densite des 8 voxels du voisinage qui vont correspondre a 1 voxel de l'image finale
# v1 = vol_work[i+j*super_sizex+k*(super_sizex*super_sizey)]
# v2 = vol_work[i+j*super_sizex+k*(super_sizex*super_sizey) + 1]
# v3 = vol_work[i+j*super_sizex+k*(super_sizex*super_sizey) + super_sizex]
# v4 = vol_work[i+j*super_sizex+k*(super_sizex*super_sizey) + super_sizex + 1]
# v5 = vol_work[i+j*super_sizex+k*(super_sizex*super_sizey) + super_sizex*super_sizey]
# v6 = vol_work[i+j*super_sizex+k*(super_sizex*super_sizey) + 1 + super_sizex*super_sizey]
# v7 = vol_work[i+j*super_sizex+k*(super_sizex*super_sizey) + super_sizex + super_sizex*super_sizey]
# v8 = vol_work[i+j*super_sizex+k*(super_sizex*super_sizey) + super_sizex + 1 + super_sizex*super_sizey]
# vol_result[x+y*sizex+z*(sizex*sizey)] = (v1+v2+v3+v4+v5+v6+v7+v8)/8.0
# print ("***",i,j,k)
total = 0
for kk in range(0, superres):
for jj in range(0, superres):
for ii in range(0, superres):
total = total + vol_work[
i + ii + (j + jj) * super_sizex + (k + kk) * (super_sizex * super_sizey)]
vol_result[x + y * sizex + z * (sizex * sizey)] = total / (superres * superres * superres)
# print ("###",vol_result[x+y*sizex+z*(sizex*sizey)])
x += 1
y += 1
x = 0
z += 1
y = 0
# Save the total volume (including the negative parts of the ellipsoids)
def save_whole_work(file):
fd = open(file, "wb")
for i in range(0, len(vol_work)):
fd.write(struct.pack("f", vol_work[i]))
# Save half the volume (including only the positive parts of the ellipsoids)
def save_half_work(file):
fd = open(file, "wb")
for i in range(int(len(vol_work) / 2), len(vol_work)):
fd.write(struct.pack("f", vol_work[i]))
# save one slice in super resolution vol_work
# 0<=slice<super_sizez
def save_workslice(file, slice):
fd = open(file, "wb")
for j in range(0, super_sizey):
for i in range(0, super_sizex):
fd.write(struct.pack("f", vol_work[i + j * super_sizex + slice * super_sizex * super_sizey]))
# Save the total result volume (including the negative parts of the ellipsoids)
def save_whole_result(file):
fd = open(file, "wb")
for i in range(0, len(vol_result)):
fd.write(struct.pack("f", vol_result[i]))
# Save half of the result volume (including only the positive parts of the ellipsoids)
def save_half_result(file):
fd = open(file, "wb")
for i in range(int(len(vol_result) / 2), len(vol_result)):
fd.write(struct.pack("f", vol_result[i]))
# save one slie in regular resolution vol_result
# 0<=slice<128
def save_slice(file, slice):
fd = open(file, "wb")
for j in range(0, sizey):
for i in range(0, sizex):
fd.write(struct.pack("f", vol_result[i + j * sizex + slice * sizex * sizey]))
print("------intialisation------")
initialize()
print("------end intialisation------")
print("------begin ellipse 1------------")
make_ellipse_center(a1, b1, c1, x1, y1, z1, rz1, value1)
print("------end ellipse 1--------------")
print("------begin ellipse 2------------")
make_ellipse_center(a2, b2, c2, x2, y2, z2, rz2, value2)
print("------end ellipse 2--------------")
print("------begin ellipse 3------------")
make_ellipse_center(a3, b3, c3, x3, y3, z3, rz3, value3)
print("------end ellipse 3--------------")
print("------begin ellipse 4------------")
make_ellipse_center(a4, b4, c4, x4, y4, z4, rz4, value4)
print("------end ellipse 4--------------")
print("------begin ellipse 5------------")
make_ellipse_center(a5, b5, c5, x5, y5, z5, rz5, value5)
print("------end ellipse 5--------------")
print("------begin ellipse 6------------")
make_ellipse_center(a6, b6, c6, x6, y6, z6, rz6, value6)
print("------end ellipse 6--------------")
print("------begin undersample------")
undersample()
print("------end undersample------")
print("The length of vol_work: ", len(vol_work))
print("The length of vol_result: ", len(vol_result))
# print ("------begin save slice 139 ------")
save_slice("./slice_139.dat", 139)
# print ("------end save slice 139 ------")
save_half_result("./vol_result.dat")
# save_whole_work("./vol_work.dat")
print("------end save work------")