CBCT simulation output (energy-integrated?)

Started by mwj12, Nov 04, 2025, 02:10 PM

Previous topic - Next topic

mwj12

*
Newbie
Posts: 26
Logged
I am new to GGEMS and trying to generate simulated CBCT projections. As an initial example, I am implementing the detector as below, with scattered detections stored separately. My question is about whether the output that gets stored is energy-integrated or not, i.e., do the photon detections get weighted by their energies when tallying the final projection image. I have heard some rumors that, while the primary detections will be energy integrated, the scattered projections may not be. Is this fake news? And if I wanted to toggle energy integration on or off, say, to simulate a photon counting detector, is there way to do that for both primary and scatter?

# TrueBeam CBCT geometry
ct_detector = GGEMSCTSystem('TrueBeam_CBCT')
ct_detector.set_ct_type('flat')
ct_detector.set_number_of_modules(1, 1)
ct_detector.set_number_of_detection_elements(193,257, 1)
ct_detector.set_size_of_detection_elements(0.776*2, 0.776*2, 0.7, 'mm')
ct_detector.set_material('CsI')
ct_detector.set_source_isocenter_distance(1000.0, 'mm')
ct_detector.set_source_detector_distance(1500.0, 'mm')
ct_detector.set_threshold(20.0, 'keV')
ct_detector.set_rotation(0.0, 0.0, -90.0, 'deg')
ct_detector.save('data/truebeam_projection')
ct_detector.store_scatter(True)

didier.benoit

Administrator
*****
Newbie
Posts: 18
Logged
There is no energy integration for CT in GGEMS. We only implemented the CT detector as a photon-counting detector, so the output is always just the number of hits (for both the final image and the scatter). It's not really a realistic CT model.
I'm not a CT specialist, but yes, I believe real CT scanners do use energy integration. So in GGEMS you're already working in photon-counting mode.

mwj12

*
Newbie
Posts: 26
Logged
#2
I see. Well, I really do need energy-integrating output. If I wished to create a new CT system class  GGEMSCTSystem_Integrating(), would you be able to point me to the files I need to modify? I would be willing to take on the coding myself, and to donate it to the repo, if there were any interest in including it. 

mwj12

*
Newbie
Posts: 26
Logged
#3
ChatGPT suggests that one could spoof energy-integrated output by expressing the x-ray source as a weighted superposition of N separate mono-energetic x-ray sources, as below. I wonder if anyone can confirm this would work.
system = GGEMSCTSystem()
for E, w in zip(E_list, w_list):
    s = GGEMSPrimarySource()
    s.SetMonoEnergy(E)
    s.SetFluenceWeight(w)
    system.AddSource(s)
system.Run()

didier.benoit

Administrator
*****
Newbie
Posts: 18
Logged
Hi,

If you want to experiment with an energy-integrating CT implementation, the relevant parts of the code are quite localised:
ggems/include/GGEMS/navigators/GGEMSCTSystem.hh
ggems/src/navigators/GGEMSCTSystem.cc
and, on the GPU side, ggems/src/TrackThroughGGEMSSolidBox.cl

That OpenCL kernel is the one handling photon hits for CT volumes defined by GGEMSSolidBox.
You'll find the key line around line 219:  atomic_add(&histogram[voxel_id.x + voxel_id.y * virtual_element_number.x], 1);

That's where each detected photon increments the count.
For an energy-integrating detector, you'd replace the fixed 1 with the photon's energy (in keV or MeV, depending on your configuration), and adapt the accumulation type accordingly.

mwj12

*
Newbie
Posts: 26
Logged
Thanks. I will ponder this.

Do you also have an opinion on the suggestion I mentioned from ChatGPT to emit with multiple sources? Is the following legitimate GGEMS code, or did ChatGPT just hallucinate this?
system = GGEMSCTSystem()
for E, w in zip(E_list, w_list):
    s = GGEMSPrimarySource()
    s.SetMonoEnergy(E)
    s.SetFluenceWeight(w)
    system.AddSource(s)
system.Run()

I think the idea here is that if you want a certain photon's energy to contribute more weight to the output, you can increase its FluenceWeight accordingly.

didier.benoit

Administrator
*****
Newbie
Posts: 18
Logged
You can already add the number of source you want in GGEMS and set the number of particles.
You have a exemple with to source here https://doc.ggems.fr/v1.3/example_6.html, you can see the macro file in 'ggems/examples/6_Visualization'. I don't have the commands that  ChatGPT wrote you, but you can implement and adapt to you case.

mwj12

*
Newbie
Posts: 26
Logged
#7
 OK. In any case, I think I found a simpler workaround. If you modify the spectrum.dat file so that fraction of photons in each row of the table is weighted by the photon energy, it should give you the same mean signal (scatter and primary?) as an energy-integrating detector. It won't give the same noise statistics, but for my present purposes, that's okay.