What is the StepTooSmall boundary process status, and can photons destroyed under this status be recovered?

I am simulating a simple gamma camera geometry with two materials and am detecting much fewer counts than expected.

Analysis of the boundary processes showed that the last photon status, just before the photon was killed, was set to “StepTooSmall” about 1/2 of the time, instead of OpAbsorption or Detection.

So what is this StepTooSmall status, and can I recover the photons killed with that status?

Below is a boundary interaction breakdown by status:

  • note that Detection are the photons entering my detector, so we get the SameMaterial status as expected)

  • The killed statuses are FresnelRefraction and StepTooSmall, neither of which make sense to me.

  • This simulation has every surface set to 100% reflectivity, so there should be no photons absorbed at all, as per my understanding.

  • The “Reflected” processes are boundary interactions that do not kill the photon (not necessarily reflection - can be reflection, refraction, or transmission)

  • The total # of photons are (1993+542+1893) + Volume_absorbed photons = 4428 + Volume_absorbed photons.
    Note that my simulation has a high opt. photon attenuation length, so the amount of Volume_absorbed is about 10 photons.


Interestingly, some boundary interactions with the StepTooSmall status are not killed, and I cannot find any calls from the StepTooSmall portion of the Geant4 source code to fStopAndKill!

(If this post is in an incorrect category, please let me know.)

I would really appreciate any insight you might have. Thank you!


This is a complicated question so we’ll need to break it down.

The optical boundary process isn’t expected to kill these photons. It will kill photons if:

  1. The photon is detected. The material property EFFICIENCY must be set > 0 and the status will be ‘Detect’.
  2. There is no RINDEX defined for one material or surface. Status will be NoRINDEX.
    These don’t appear to apply in your case.

Do you have something else that kills photons? How do you know they’re killed? Can you see it with /tracking/verbose 2 ?

What do you mean be ‘Detection’? As noted above, detected photons should have status Detected.

Are you able to reproduce this with example OpNovice2?

Thank you, Mr. Sawkey.

  1. I have EFFICIENCY set to 1, but as REFLECTIVITY is set to 1 for all materials (debugging purposes), at present there are never any detections; if I lower REFLECTIVITY, as expected, there are some detected photons with status Detected.

  2. I have double checked this - cannot be the case.

The only other process that kills photons (as far as I know) would be the one corresponding to volumetric absorption. The list of statuses above corresponds to only boundary effects, so that cannot be the case.

I have not tried /tracking/verbose 2. I will do so and let you know.

‘Detection’: I have a special edit in my SteppingAction - if any photon enters the detectors (not the camera itself, but the silicon photomultipliers), then I manually set the track status to fStopAndKill, so as to not double count the photons. This is why I get a ‘SameMaterial’ status instead of a ‘Detected’ status.
It may be more appropriate to just change REFLECTIVITY and EFFICIENCY for the silicon photomultipliers, but my setup ought not affect anything else.

As far as reproducing this with OpNovice2, this behavior is not unique to my simulation:
I found a paper from the Universidade de Santiago de Compostela that has several photons killed with status set to ‘StepTooSmall’. I have attached images from their paper for reference.

The link to the paper: http://igfae.usc.es/~genp/academic/dea/DEA_Paloma.pdf

Running tracking/verbose 1 listed the processes as one of [Transportation, OpRayleigh, OpAbsorption], as expected. (Somehow, for my simulation, tracking/verbose 1 and tracking/verbose 2 gave identical results.)
Very rarely is OpAbsorption listed (that would be volumetric or surface absorption)
Note that we expect no surface absorption, and only a few percent volumetric absorption.

The last few processes of an optical photon track are listed below:

  • Note the volumes with EJ208 are scintillator strips, while the Vikuiti volumes wrap the EJ208 scintillators (metallic foil for photon reflection).

As far as I can tell, the last few moments of the track consist of the photon bouncing in between the Vikuiti wrapper and the EJ208 scintillator.
So I would expect an ‘OpAbsorption’ process hidden in the ‘Transportation’ process here.

Running with tracking/verbose 3:

I have attached the last step of a photon:
laststeps.txt (3.2 KB)
Why is there an OpAbsorption where there should be none?

I really appreciate your help. Thank you.


Try adding

/process/optical/boundary/verbose 2

to your macro. What you should see (example below) is that when a photon interacts at the boundary, there will often be two navigator steps at the same position. The first is what is really going on (status of e.g. FresnelReflection) and the second is internal workings of the boundary process (status StepTooSmall). Thus, if you are counting boundary interactions, don’t count the StepTooSmall or else you will double count. This is what happens in steps 374/375 of your tracking output. (look for step length = 0).

You’ll also see Transportation given as the process that limits the step. This means the photon reached another volume. All relevant processes still occur during the step, including OpBoundary if applicable.

In step 386 of your printout, the photon loses all its kinetic energy at the boundary. The printout doesn’t say why, but the verbose command above should help. Likely the photon is detected, in the optical boundary process sense of the word.

If a photon is absorbed by the G4OpBoundaryProcess, it is G4OpBoundaryProcess that does it, not G4OpAbsorption.

REFLECTIVITY is really 1-ABSORPTION at the boundary. And, EFFICIENCY is the fraction of fraction of absorbed photons that are detected. So, it’s not logical to set both REFLECTIVITY and EFFICIENCY to 1. No photons will be absorbed or detected.

Example output (edited for brevity):

G4WT0 > Step#    X(mm)    Y(mm)    Z(mm) KinE(MeV)  dE(MeV) StepLeng TrackLeng  NextVolume ProcName
G4WT0 >  Photon at Boundary!
G4WT0 >  thePrePV:  Tank
G4WT0 >  thePostPV: World
G4WT0 >  *** FresnelReflection ***
G4WT0 >     1    1e+03      489        0     3e-06        0 1.11e+03  1.11e+03       World Transportation
G4WT0 >  Photon at Boundary!
G4WT0 >  thePrePV:  World
G4WT0 >  thePostPV: Tank
G4WT0 >  *** StepTooSmall ***
G4WT0 >     2    1e+03      489        0     3e-06        0        0  1.11e+03        Tank Transportation

Unfortunately, this command did not change anything - I will probably need to read the verbosity section in the documentation more carefully.

Thank you for this insight; it is quite likely that I am double counting.
I will try it and get back to you. Thank you.

This is exactly what I am trying to do (for the scintillator material, there should only be volumetric absorption and absolutely no boundary absorption - efficiency is irrelevant)! Boundary absorption would only occur if we have dust/other material on the surface or skin effects, which I am ignoring at present.

So I am using an if statement as follows (after confirming that the primary particle is an optical photon) in SteppingAction:

My new results are:
with total # of photons: 4477, (9 Volume-absorbed, the rest (4468) either boundary-absorbed or SiPM detected).

Clearly my “Reflected” category is no longer double counting the StepTooSmall status (we now have 21 instead of 1106143), but I am still getting several processes with a StepTooSmall status and a non-zero step length that kill photons.

I know that there is no double counting in terms of “Killed & Detection” categories, as these are unique boundary interactions that sum to the total # of photons:

  • 2034 detections + 522 killed by refraction + 1912 killed by StepTooSmall = 4468 photons stopped at some boundary. (Note that there is very little volumetric attenuation, so this should be close to the total # of photons.)

The total # of photons is 4477, which is as expected:

  • EJ208 produces 9200 photons/MeV, so at 511MeV gammas, it would produce around 4700 photons in an event.

If I were to remove the StepTooSmall category entirely, then there would be undercounting, as 2034+522 = 2556, much less than 4477.

How would I find the process that generates the StepTooSmall status? It seems that the step prior to the StepTooSmall may have been misclassified as a “Reflection/Refraction” by my code, since the photon is not killed in that step.

Do you know of a way to count these boundary processes only once, without this misclassification?

Thank you.

Yes–it’s why I suggested example OpNovice2 at the start!

1 Like