Skip to content

Commit 343e59c

Browse files
authored
Merge pull request #1005 from OpenGATE/ffd
2 parents fa8f4c1 + 6825bc8 commit 343e59c

11 files changed

Lines changed: 1612 additions & 39 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ opengate_temporaire
9494
/opengate/tests/src/test030_save
9595
/opengate/tests/src/test_log*
9696
/opengate/tests/src/save_tests
97+
/opengate/tests/src/external/coresi/logs/*
98+
/opengate/tests/src/external/coresi/checkpoi*
9799

98100
/opengate/data/isomeric_transition/save
99101
/opengate/data/isomeric_transition/save2

core/opengate_core/opengate_lib/GateFluenceActor.cpp

Lines changed: 312 additions & 9 deletions
Large diffs are not rendered by default.

core/opengate_core/opengate_lib/GateFluenceActor.h

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
#define GateFluenceActor_h
1010

1111
#include "G4Cache.hh"
12+
#include "G4EmCalculator.hh"
1213
#include "G4VPrimitiveScorer.hh"
1314
#include "GateVActor.h"
15+
#include "digitizer/GateDigiAttributeLastProcessDefinedStepInVolumeActor.h"
1416
#include "itkImage.h"
1517
#include <iostream>
1618
#include <pybind11/stl.h>
@@ -29,16 +31,25 @@ class GateFluenceActor : public GateVActor {
2931

3032
// Function called every step in attached volume
3133
// This where the scoring takes place
34+
3235
void SteppingAction(G4Step *) override;
3336

37+
void StartSimulationAction() override;
38+
3439
void BeginOfEventAction(const G4Event *event) override;
3540

41+
void EndOfEventAction(const G4Event *event) override;
42+
3643
void BeginOfRunActionMasterThread(int run_id) override;
3744

45+
void BeginOfRunAction(const G4Run *run) override;
46+
3847
inline std::string GetPhysicalVolumeName() { return fPhysicalVolumeName; }
3948

4049
inline void SetPhysicalVolumeName(std::string s) { fPhysicalVolumeName = s; }
4150

51+
int fNbOfEvent;
52+
4253
int NbOfEvent = 0;
4354

4455
// Image type is 3D float by default
@@ -49,7 +60,77 @@ class GateFluenceActor : public GateVActor {
4960
Size4DType size_4D;
5061

5162
// The image is accessible on py side (shared by all threads)
52-
Image3DType::Pointer cpp_fluence_image;
63+
Image3DType::Pointer cpp_counts_image;
64+
Image3DType::Pointer cpp_counts_compton_image;
65+
Image3DType::Pointer cpp_counts_rayleigh_image;
66+
Image3DType::Pointer cpp_counts_secondaries_image;
67+
Image3DType::Pointer cpp_counts_primaries_image;
68+
69+
Image3DType::Pointer cpp_energy_image;
70+
Image3DType::Pointer cpp_energy_compton_image;
71+
Image3DType::Pointer cpp_energy_rayleigh_image;
72+
Image3DType::Pointer cpp_energy_secondaries_image;
73+
Image3DType::Pointer cpp_energy_primaries_image;
74+
75+
Image3DType::Pointer cpp_counts_squared_image;
76+
Image3DType::Pointer cpp_counts_squared_compton_image;
77+
Image3DType::Pointer cpp_counts_squared_rayleigh_image;
78+
Image3DType::Pointer cpp_counts_squared_secondaries_image;
79+
Image3DType::Pointer cpp_counts_squared_primaries_image;
80+
81+
Image3DType::Pointer cpp_energy_squared_image;
82+
Image3DType::Pointer cpp_energy_squared_compton_image;
83+
Image3DType::Pointer cpp_energy_squared_rayleigh_image;
84+
Image3DType::Pointer cpp_energy_squared_secondaries_image;
85+
Image3DType::Pointer cpp_energy_squared_primaries_image;
86+
87+
Image3DType::SizeType size_region{};
88+
89+
struct threadLocalT {
90+
G4EmCalculator emcalc;
91+
std::vector<double> squared_worker_flatimg;
92+
std::vector<int> lastid_worker_flatimg;
93+
};
94+
95+
G4Cache<threadLocalT> fThreadLocalDataCounts;
96+
G4Cache<threadLocalT> fThreadLocalDataComptCounts;
97+
G4Cache<threadLocalT> fThreadLocalDataRaylCounts;
98+
G4Cache<threadLocalT> fThreadLocalDataSecCounts;
99+
G4Cache<threadLocalT> fThreadLocalDataPrimCounts;
100+
G4Cache<threadLocalT> fThreadLocalDataEnergy;
101+
G4Cache<threadLocalT> fThreadLocalDataComptEnergy;
102+
G4Cache<threadLocalT> fThreadLocalDataRaylEnergy;
103+
G4Cache<threadLocalT> fThreadLocalDataSecEnergy;
104+
G4Cache<threadLocalT> fThreadLocalDataPrimEnergy;
105+
106+
G4bool fCountsSquaredFlag;
107+
G4bool fEnergyFlag;
108+
G4bool fEnergySquaredFlag;
109+
G4bool fSecondaries;
110+
GateDigiAttributeLastProcessDefinedStepInVolumeActor *fLastProcessActor;
111+
// GateVActor* fLastProcessActor;
112+
113+
void FlushSquaredValues(threadLocalT &data,
114+
const Image3DType::Pointer &cpp_image);
115+
void ScoreSquaredValue(threadLocalT &data,
116+
const Image3DType::Pointer &cpp_image,
117+
const double value, const int event_id,
118+
const Image3DType::IndexType &index);
119+
int sub2ind(Image3DType::IndexType index3D);
120+
void PrepareLocalDataForRun(threadLocalT &data,
121+
const unsigned int numberOfVoxels);
122+
123+
bool GetEnergySquaredFlag() const { return fEnergySquaredFlag; }
124+
125+
void SetEnergySquaredFlag(const bool b) { fEnergySquaredFlag = b; }
126+
127+
void SetEnergyFlag(const bool b) { fEnergyFlag = b; }
128+
129+
bool GetEnergyFlag() const { return fEnergyFlag; }
130+
131+
void SetCountsSquaredFlag(const bool b) { fCountsSquaredFlag = b; }
132+
133+
bool GetCountsSquaredFlag() const { return fCountsSquaredFlag; }
53134

54135
private:
55136
std::string fPhysicalVolumeName;

core/opengate_core/opengate_lib/biasing/GateScatterSplittingFreeFlightOptn.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,13 @@ G4VParticleChange *GateScatterSplittingFreeFlightOptn::ApplyFinalStateBiasing(
6060
const G4BiasingProcessInterface *callingProcess, const G4Track *track,
6161
const G4Step *step, G4bool &b) {
6262
// This is the reference pure G4 version
63-
// return ApplyFinalStateBiasing_V1_PostStepDoIt(callingProcess, track, step,
64-
// b);
63+
return ApplyFinalStateBiasing_V1_PostStepDoIt(callingProcess, track, step, b);
6564

6665
// This is a faster (1x5 speedup) version with direct Compton sampling
6766
// return ApplyFinalStateBiasing_V3_SampleScatter(callingProcess, track, step,
6867
// b);
69-
return ApplyFinalStateBiasing_V4_SampleComptonOnly(callingProcess, track,
70-
step, b);
68+
// return ApplyFinalStateBiasing_V4_SampleComptonOnly(callingProcess, track,
69+
// step, b);
7170

7271
// Those are tests, not conclusive
7372
// return ApplyFinalStateBiasing_V2_SampleSecondaries(callingProcess, track,

core/opengate_core/opengate_lib/pyGateFluenceActor.cpp

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,49 @@ void init_GateFluenceActor(py::module &m) {
3939
&GateFluenceActor::EndOfRunActionMasterThread)
4040
.def("GetPhysicalVolumeName", &GateFluenceActor::GetPhysicalVolumeName)
4141
.def("SetPhysicalVolumeName", &GateFluenceActor::SetPhysicalVolumeName)
42+
.def("GetEnergySquaredFlag", &GateFluenceActor::GetEnergySquaredFlag)
43+
.def("SetEnergySquaredFlag", &GateFluenceActor::SetEnergySquaredFlag)
44+
.def("GetEnergyFlag", &GateFluenceActor::GetEnergyFlag)
45+
.def("SetEnergyFlag", &GateFluenceActor::SetEnergyFlag)
46+
.def("GetCountsSquaredFlag", &GateFluenceActor::GetCountsSquaredFlag)
47+
.def("SetCountsSquaredFlag", &GateFluenceActor::SetCountsSquaredFlag)
4248
.def_readwrite("NbOfEvent", &GateFluenceActor::NbOfEvent)
43-
.def_readwrite("cpp_fluence_image", &GateFluenceActor::cpp_fluence_image);
49+
.def_readwrite("cpp_counts_image", &GateFluenceActor::cpp_counts_image)
50+
.def_readwrite("cpp_energy_image", &GateFluenceActor::cpp_energy_image)
51+
.def_readwrite("cpp_counts_squared_image",
52+
&GateFluenceActor::cpp_counts_squared_image)
53+
.def_readwrite("cpp_energy_squared_image",
54+
&GateFluenceActor::cpp_energy_squared_image)
55+
.def_readwrite("cpp_counts_compton_image",
56+
&GateFluenceActor::cpp_counts_compton_image)
57+
.def_readwrite("cpp_energy_compton_image",
58+
&GateFluenceActor::cpp_energy_compton_image)
59+
.def_readwrite("cpp_counts_squared_compton_image",
60+
&GateFluenceActor::cpp_counts_squared_compton_image)
61+
.def_readwrite("cpp_energy_squared_compton_image",
62+
&GateFluenceActor::cpp_energy_squared_compton_image)
63+
.def_readwrite("cpp_counts_rayleigh_image",
64+
&GateFluenceActor::cpp_counts_rayleigh_image)
65+
.def_readwrite("cpp_energy_rayleigh_image",
66+
&GateFluenceActor::cpp_energy_rayleigh_image)
67+
.def_readwrite("cpp_counts_squared_rayleigh_image",
68+
&GateFluenceActor::cpp_counts_squared_rayleigh_image)
69+
.def_readwrite("cpp_energy_squared_rayleigh_image",
70+
&GateFluenceActor::cpp_energy_squared_rayleigh_image)
71+
.def_readwrite("cpp_counts_secondaries_image",
72+
&GateFluenceActor::cpp_counts_secondaries_image)
73+
.def_readwrite("cpp_energy_secondaries_image",
74+
&GateFluenceActor::cpp_energy_secondaries_image)
75+
.def_readwrite("cpp_counts_squared_secondaries_image",
76+
&GateFluenceActor::cpp_counts_squared_secondaries_image)
77+
.def_readwrite("cpp_energy_squared_secondaries_image",
78+
&GateFluenceActor::cpp_energy_squared_secondaries_image)
79+
.def_readwrite("cpp_counts_primaries_image",
80+
&GateFluenceActor::cpp_counts_primaries_image)
81+
.def_readwrite("cpp_energy_primaries_image",
82+
&GateFluenceActor::cpp_energy_primaries_image)
83+
.def_readwrite("cpp_counts_squared_primaries_image",
84+
&GateFluenceActor::cpp_counts_squared_primaries_image)
85+
.def_readwrite("cpp_energy_squared_primaries_image",
86+
&GateFluenceActor::cpp_energy_squared_primaries_image);
4487
}

docs/source/user_guide/user_guide_reference_actors.rst

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,31 @@ FluenceActor
305305
Description
306306
~~~~~~~~~~~
307307

308-
This actor scores the particle fluence on a voxel grid, essentially by counting the number of particles passing through each voxel. The FluenceActor will be extended in the future with features to handle scattered radiation, e.g. in cone beam CT imaging.
308+
This actor scores the particle fluence on a voxel grid, essentially by counting the number of particles passing through each voxel. When a particle enters a voxel, it records either the counts or the kinetic energy of the incoming particle. If a particle is created within a voxel of the geometry to which the Fluence Actor is attached, this particle is not counted as part of the incoming flux for that voxel. A basic example of its usage is provided below:
309309

310+
.. code-block:: python
311+
312+
fluence_actor = sim.add_actor("FluenceActor", "fluence_actor")
313+
fluence_actor.counts_uncertainty.active = True
314+
fluence_actor.counts_squared.active = True
315+
fluence_actor.energy.active = True
316+
fluence_actor.energy_uncertainty.active = True
317+
fluence_actor.energy_squared.active = True
318+
fluence_actor.output_filename = "test099.mhd"
319+
fluence_actor.attached_to = fluence_plane
320+
fluence_actor.size = [10, 10, 1]
321+
ts = [10 * cm, 10 * cm, 1 * nm]
322+
fluence_actor.spacing = [x / y for x, y in zip(ts, fluence_actor.size)]
323+
fluence_actor.hit_type = "random"
324+
325+
326+
In addition, it is possible to generate separate fluence maps resolving the particle's tracking state and underlying physics processes (`primaries`, `secondaries`, `compton`, and `rayleigh`). These maps are created as follows: particles originating directly from the source without interacting are recorded as `primaries`, while all others are recorded as `secondaries`. Furthermore, if the incoming particle is a gamma photon and its last interaction was either Compton or Rayleigh scattering, the counts (and optionally the photon energy) are also recorded in the corresponding scattering-process maps. At present, pair production is not yet included as a recordable process. This actor is also compatible with the FreeFlightAngularAcceptance variance reduction technique. To enable the recording of these additional maps, simply set the following boolean to True:
327+
328+
.. code-block:: python
329+
330+
fluence_actor.score_by_process = True
331+
332+
The activation of the squared counts (and energies) and their associated uncertainty maps is handled automatically, according to the global settings defined by the user for counts and energy scoring.
310333

311334
Reference
312335
~~~~~~~~~

0 commit comments

Comments
 (0)